From 93424f74c04c8090f4213cec071bc2121724ad18 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Sun, 8 Aug 2021 18:42:07 -0700 Subject: [PATCH] Throw autolayout behind a feature flag. - AutoLayout is now behind a feature flag (that is defaulted) to enable building and running on platforms that do _not_ support AutoLayout. - Added a frame-based Layout example for platforms that don't have AutoLayout support. - Fixed a bug in geometry.rs where x/y coordinates would get swapped on conversion to `CGRect`. - Added a README to the examples directory to aid in first time users running examples. --- Cargo.toml | 3 +- examples/frame_layout.rs | 115 ++++++++++++++++++++++ examples/ios-beta/readme.md | 2 +- examples/readme.md | 64 +++++++++++++ src/button/mod.rs | 39 +++++++- src/geometry.rs | 2 +- src/image/mod.rs | 37 +++++++- src/input/mod.rs | 136 +++++++++++++++++++++------ src/layout/mod.rs | 33 ++++--- src/layout/traits.rs | 1 + src/lib.rs | 3 + src/listview/mod.rs | 140 ++++++++++++++++++++------- src/listview/row/mod.rs | 183 +++++++++++++++++++++++++++++------- src/progress/mod.rs | 41 +++++++- src/scrollview/mod.rs | 81 +++++++++++++++- src/switch.rs | 60 +++++++++--- src/text/label/mod.rs | 83 +++++++++++++++- src/view/mod.rs | 59 +++++++++++- src/webview/mod.rs | 78 ++++++++++++--- 19 files changed, 1012 insertions(+), 148 deletions(-) create mode 100644 examples/frame_layout.rs create mode 100644 examples/readme.md diff --git a/Cargo.toml b/Cargo.toml index bdb6a7d..e4def77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,8 @@ eval = "0.4" [features] appkit = ["core-foundation/mac_os_10_8_features"] uikit = [] -default = ["appkit"] +autolayout = [] +default = ["appkit", "autolayout"] cloudkit = [] color_fallbacks = [] quicklook = [] diff --git a/examples/frame_layout.rs b/examples/frame_layout.rs new file mode 100644 index 0000000..c486ae3 --- /dev/null +++ b/examples/frame_layout.rs @@ -0,0 +1,115 @@ +//! This example showcases setting up a basic application and window, setting up some views to +//! work with autolayout, and some basic ways to handle colors. + +use cacao::color::Color; +use cacao::geometry::Rect; +use cacao::layout::Layout; +use cacao::view::View; + +use cacao::appkit::{App, AppDelegate}; +use cacao::appkit::menu::{Menu, MenuItem}; +use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; + +struct BasicApp { + window: Window +} + +impl AppDelegate for BasicApp { + fn did_finish_launching(&self) { + App::set_menu(vec![ + Menu::new("", vec![ + MenuItem::Services, + MenuItem::Separator, + MenuItem::Hide, + MenuItem::HideOthers, + MenuItem::ShowAll, + MenuItem::Separator, + MenuItem::Quit + ]), + + Menu::new("File", vec![ + MenuItem::CloseWindow + ]), + + Menu::new("View", vec![ + MenuItem::EnterFullScreen + ]), + + Menu::new("Window", vec![ + MenuItem::Minimize, + MenuItem::Zoom, + MenuItem::Separator, + MenuItem::new("Bring All to Front") + ]) + ]); + + App::activate(); + + self.window.show(); + } + + fn should_terminate_after_last_window_closed(&self) -> bool { + true + } +} + +#[derive(Default)] +struct AppWindow { + content: View, + blue: View, + red: View, + green: View +} + +const CORNER_RADIUS: f64 = 16.; +const SPACING: f64 = 10.; +const TOP: f64 = 40.; +const WIDTH: f64 = 100.; +const HEIGHT: f64 = 100.; + +impl WindowDelegate for AppWindow { + const NAME: &'static str = "WindowDelegate"; + + fn did_load(&mut self, window: Window) { + window.set_title("Frame Layout Example"); + window.set_minimum_content_size(300., 300.); + + self.blue.set_background_color(Color::SystemBlue); + self.blue.set_frame(Rect { + top: TOP, + left: SPACING, + width: WIDTH, + height: HEIGHT + }); + self.blue.layer.set_corner_radius(CORNER_RADIUS); + self.content.add_subview(&self.blue); + + self.red.set_background_color(Color::SystemRed); + self.red.set_frame(Rect { + top: TOP, + left: WIDTH + (SPACING * 2.), + width: WIDTH, + height: HEIGHT + }); + self.red.layer.set_corner_radius(CORNER_RADIUS); + self.content.add_subview(&self.red); + + self.green.set_background_color(Color::SystemGreen); + self.green.set_frame(Rect { + top: TOP, + left: (WIDTH * 2.) + (SPACING * 3.), + width: WIDTH, + height: HEIGHT + }); + self.green.layer.set_corner_radius(CORNER_RADIUS); + self.content.add_subview(&self.green); + + window.set_content_view(&self.content); + } +} + +fn main() { + App::new("com.test.window", BasicApp { + window: Window::with(WindowConfig::default(), AppWindow::default()) + }).run(); +} diff --git a/examples/ios-beta/readme.md b/examples/ios-beta/readme.md index 571ec55..5dc4a32 100644 --- a/examples/ios-beta/readme.md +++ b/examples/ios-beta/readme.md @@ -6,7 +6,7 @@ Since this needs to run in an iOS simulator or on a device, you can't run it lik - Start a simulator (Simulator.app). - `cargo install cargo-bundle` -- `cargo bundle --example ios-beta --target x86_64-apple-ios` +- `cargo bundle --example ios-beta --no-default-features --features uikit,autolayout --target x86_64-apple-ios` - `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` diff --git a/examples/readme.md b/examples/readme.md new file mode 100644 index 0000000..4c90ffe --- /dev/null +++ b/examples/readme.md @@ -0,0 +1,64 @@ +# Cacao Examples +This directory contains example code for apps written in cacao. To run an example, check out the list of commands below - some require certain features to be enabled. + +## AutoLayout +An example that showcases layout out a view with AutoLayout. This requires the feature flag `autolayout` to be enabled, but it's defaulted for ease of use so doesn't need to be specified here. Platforms where AutoLayout is not supported will likely not work with this example. + +`cargo run --example autolayout` + +## Frame Layout +An example that showcases laying out with a more old school Frame-based approach. Platforms where AutoLayout are not supported will want to try this instead of the AutoLayout example. + +**macOS:** +`cargo run --example frame_layout` + +**Platforms lacking AutoLayout:** +`cargo run --example frame_layout --no-default-features --features appkit` + +## Defaults +This example isn't GUI-specific, but showcases accessing `NSUserDefaults` from Rust for persisting basic data. + +`cargo run --example defaults` + +## Window +This example showcases creating a basic `Window`. This should run on all AppKit-supporting platforms. + +`cargo run --example window` + +## Window Controller +This example showcases creating a basic `WindowController`. This may run on all AppKit-supporting platforms. + +`cargo run --example window_controller` + +## Window Delegate +This example showcases creating a basic `WindowDelegate` to receive and handle events. This may run on all AppKit-supporting platforms. + +`cargo run --example window_delegate` + +## Text Input +This example showcases text input, and logs it to the underlying console. It's mostly a testbed to ensure that the backing widget for input behaves as expected. + +`cargo run --example text_input` + +## Calculator +A Rust-rendition of the macOS Calculator app. + +`cargo run --example calculator` + +## To-Do List +A "kitchen sink" example that showcases how to do more advanced things, such as cached reusable ListView components. + +`cargo run --example todos_list` + +## Browser +A _very_ basic web browser. Platforms that don't support WKWebView will likely not work with this example. + +`cargo run --example browser --features webview` + +## Webview Custom Protocol +This example showcases a custom protocol for the webview feature. Platforms that don't support WKWebView will likely not work with this example. + +`cargo run --example webview_custom_protocol --features webview` + +## iOS (Beta) +This example showcases how to build and run an iOS app in Rust. See the README in the `ios-beta` folder for instructions on how to run. diff --git a/src/button/mod.rs b/src/button/mod.rs index 00bc849..2eb4502 100644 --- a/src/button/mod.rs +++ b/src/button/mod.rs @@ -32,10 +32,13 @@ use crate::color::Color; use crate::image::Image; use crate::foundation::{id, nil, BOOL, YES, NO, NSString, NSUInteger}; use crate::invoker::TargetActionHandler; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::text::{AttributedString, Font}; use crate::utils::{load, properties::ObjcProperty}; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] use crate::appkit::FocusRingType; @@ -71,33 +74,43 @@ pub struct Button { handler: Option, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -114,23 +127,47 @@ impl Button { ]; let _: () = msg_send![button, setWantsLayer:YES]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO]; + button }; Button { handler: None, image: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), } } diff --git a/src/geometry.rs b/src/geometry.rs index cd8d529..547202a 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -39,7 +39,7 @@ impl Rect { impl From for CGRect { fn from(rect: Rect) -> CGRect { CGRect::new( - &CGPoint::new(rect.top, rect.left), + &CGPoint::new(rect.left, rect.top), &CGSize::new(rect.width, rect.height) ) } diff --git a/src/image/mod.rs b/src/image/mod.rs index 4a0f177..c5d40c0 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -4,9 +4,12 @@ use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::color::Color; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] mod appkit; @@ -29,6 +32,8 @@ pub use icons::*; fn allocate_view(registration_fn: fn() -> *const Class) -> id { unsafe { let view: id = msg_send![registration_fn(), new]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -47,33 +52,43 @@ pub struct ImageView { pub objc: ObjcProperty, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -89,16 +104,36 @@ impl ImageView { let view = allocate_view(register_image_view_class); ImageView { + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), } } diff --git a/src/input/mod.rs b/src/input/mod.rs index c9c0075..24d8764 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -46,10 +46,13 @@ use objc_id::ShareId; use crate::color::Color; use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NO, YES}; -use crate::layout::{Layout, LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}; +use crate::layout::Layout; use crate::text::{Font, TextAlign}; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}; + #[cfg(feature = "appkit")] mod appkit; @@ -72,6 +75,7 @@ fn common_init(class: *const Class) -> id { unsafe { let view: id = msg_send![class, new]; + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO]; #[cfg(feature = "appkit")] @@ -92,33 +96,43 @@ pub struct TextField { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY, } @@ -136,17 +150,37 @@ impl TextField { TextField { delegate: None, - top: LayoutAnchorY::top(view), - left: LayoutAnchorX::left(view), - leading: LayoutAnchorX::leading(view), - right: LayoutAnchorX::right(view), - trailing: LayoutAnchorX::trailing(view), - bottom: LayoutAnchorY::bottom(view), - width: LayoutAnchorDimension::width(view), - height: LayoutAnchorDimension::height(view), - center_x: LayoutAnchorX::center(view), - center_y: LayoutAnchorY::center(view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(view) } } } @@ -169,17 +203,37 @@ where let mut label = TextField { delegate: None, - top: LayoutAnchorY::top(label), - left: LayoutAnchorX::left(label), - leading: LayoutAnchorX::leading(label), - right: LayoutAnchorX::right(label), - trailing: LayoutAnchorX::trailing(label), - bottom: LayoutAnchorY::bottom(label), - width: LayoutAnchorDimension::width(label), - height: LayoutAnchorDimension::height(label), - center_x: LayoutAnchorX::center(label), - center_y: LayoutAnchorY::center(label), objc: ObjcProperty::retain(label), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(label), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(label), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(label), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(label), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(label), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(label), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(label), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(label), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(label), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(label), }; (&mut delegate).did_load(label.clone_as_handle()); @@ -196,17 +250,37 @@ impl TextField { pub(crate) fn clone_as_handle(&self) -> TextField { TextField { delegate: None, - top: self.top.clone(), - leading: self.leading.clone(), - left: self.left.clone(), - trailing: self.trailing.clone(), - right: self.right.clone(), - bottom: self.bottom.clone(), - width: self.width.clone(), - height: self.height.clone(), - center_x: self.center_x.clone(), - center_y: self.center_y.clone(), objc: self.objc.clone(), + + #[cfg(feature = "autolayout")] + top: self.top.clone(), + + #[cfg(feature = "autolayout")] + leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] + left: self.left.clone(), + + #[cfg(feature = "autolayout")] + trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] + right: self.right.clone(), + + #[cfg(feature = "autolayout")] + bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] + width: self.width.clone(), + + #[cfg(feature = "autolayout")] + height: self.height.clone(), + + #[cfg(feature = "autolayout")] + center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] + center_y: self.center_y.clone(), } } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 36afe80..1921461 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,26 +1,37 @@ -//! A wrapper for `NSLayoutConstraint`, enabling AutoLayout across views. This does a few things -//! that might seem weird, but are generally good and rely on the idea that this is all written -//! once and used often. -//! -//! Notably: there are 3 structs for wrapping layout constraints; in practice, you likely don't need to -//! care. This is because we want to detect at compile time invalid layout items - i.e, you should -//! not be able to attach a left-axis to a top-axis. In Rust this is a bit tricky, but by using -//! some `impl Trait`'s in the right places we can mostly hide this detail away. - -pub mod attributes; -pub use attributes::*; +//! This module contains traits and helpers for layout. By default, standard frame-based layouts +//! are supported via the `Layout` trait, which all widgets implement. If you opt in to the +//! `AutoLayout` feature, each widget will default to using AutoLayout, which can be beneficial in +//! more complicated views that need to deal with differing screen sizes. pub mod traits; pub use traits::Layout; +#[cfg(feature = "autolayout")] +pub mod attributes; + +#[cfg(feature = "autolayout")] +pub use attributes::*; + +#[cfg(feature = "autolayout")] pub mod constraint; + +#[cfg(feature = "autolayout")] pub use constraint::LayoutConstraint; +#[cfg(feature = "autolayout")] pub mod dimension; + +#[cfg(feature = "autolayout")] pub use dimension::LayoutAnchorDimension; +#[cfg(feature = "autolayout")] pub mod horizontal; + +#[cfg(feature = "autolayout")] pub use horizontal::LayoutAnchorX; +#[cfg(feature = "autolayout")] pub mod vertical; + +#[cfg(feature = "autolayout")] pub use vertical::LayoutAnchorY; diff --git a/src/layout/traits.rs b/src/layout/traits.rs index 283611b..74976bc 100644 --- a/src/layout/traits.rs +++ b/src/layout/traits.rs @@ -71,6 +71,7 @@ pub trait Layout { /// /// Cacao defaults this to `false`; if you need to set frame-based layout pieces, /// then you should set this to `true` (or use an appropriate initializer that does it for you). + #[cfg(feature = "autolayout")] fn set_translates_autoresizing_mask_into_constraints(&self, translates: bool) { self.with_backing_node(|backing_node| unsafe { let _: () = msg_send![backing_node, setTranslatesAutoresizingMaskIntoConstraints:match translates { diff --git a/src/lib.rs b/src/lib.rs index 477a95b..4f2ee1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,9 @@ pub use objc; pub use url; pub use lazy_static; +#[cfg(all(feature = "appkit", feature = "uikit", not(feature = "no-intrinsics")))] +compile_error!("The \"appkit\" and \"uikit\" features cannot be enabled together. Pick one. :)"); + #[cfg(feature = "appkit")] #[cfg_attr(docsrs, doc(cfg(target_os = "appkit")))] pub mod appkit; diff --git a/src/listview/mod.rs b/src/listview/mod.rs index 0a60f16..6f20180 100644 --- a/src/listview/mod.rs +++ b/src/listview/mod.rs @@ -50,7 +50,12 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString, NSInteger, NSUInteger}; use crate::color::Color; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + +use crate::layout::Layout; + +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + use crate::scrollview::ScrollView; use crate::utils::{os, CellFactory, CGSize}; use crate::utils::properties::{ObjcProperty, PropertyNullable}; @@ -95,6 +100,8 @@ use std::cell::RefCell; fn common_init(class: *const Class) -> id { unsafe { let tableview: id = msg_send![class, new]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![tableview, setTranslatesAutoresizingMaskIntoConstraints:NO]; // Let's... make NSTableView into UITableView-ish. @@ -139,40 +146,51 @@ pub struct ListView { /// In AppKit, we need to manage the NSScrollView ourselves. It's a bit /// more old school like that... - #[cfg(feature = "appkit")] + /// + /// In iOS, this is a pointer to the UITableView-owned UIScrollView. pub scrollview: ScrollView, /// A pointer to the delegate for this view. pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -201,32 +219,52 @@ impl ListView { // For AppKit, we need to use the NSScrollView anchor points, not the NSTableView. // @TODO: Fix this with proper mutable access. - #[cfg(feature = "appkit")] + #[cfg(all(feature = "appkit", feature = "autolayout"))] let anchor_view: id = scrollview.objc.get(|obj| unsafe { msg_send![obj, self] }); - #[cfg(target_os = "ios")] - let anchor_view: id = view; + //#[cfg(all(feature = "uikit", feature = "autolayout"))] + //let anchor_view: id = view; ListView { cell_factory: CellFactory::new(), menu: PropertyNullable::default(), delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(anchor_view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(anchor_view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(anchor_view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(anchor_view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(anchor_view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(anchor_view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(anchor_view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(anchor_view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(anchor_view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(anchor_view), + objc: ObjcProperty::retain(view), - #[cfg(feature = "appkit")] - scrollview: scrollview + scrollview } } } @@ -241,8 +279,6 @@ impl ListView where T: ListViewDelegate + 'static { let cell = CellFactory::new(); unsafe { - //let view: id = msg_send![register_view_class_with_delegate::(), new]; - //let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let delegate_ptr: *const T = &*delegate; (&mut *view).set_ivar(LISTVIEW_DELEGATE_PTR, delegate_ptr as usize); let _: () = msg_send![view, setDelegate:view]; @@ -261,7 +297,7 @@ impl ListView where T: ListViewDelegate + 'static { }; // For AppKit, we need to use the NSScrollView anchor points, not the NSTableView. - #[cfg(feature = "appkit")] + #[cfg(all(feature = "appkit", feature = "autolayout"))] let anchor_view: id = scrollview.objc.get(|obj| unsafe { msg_send![obj, self] }); @@ -273,20 +309,39 @@ impl ListView where T: ListViewDelegate + 'static { cell_factory: cell, menu: PropertyNullable::default(), delegate: None, - top: LayoutAnchorY::top(anchor_view), - left: LayoutAnchorX::left(anchor_view), - leading: LayoutAnchorX::leading(anchor_view), - right: LayoutAnchorX::right(anchor_view), - trailing: LayoutAnchorX::trailing(anchor_view), - bottom: LayoutAnchorY::bottom(anchor_view), - width: LayoutAnchorDimension::width(anchor_view), - height: LayoutAnchorDimension::height(anchor_view), - center_x: LayoutAnchorX::center(anchor_view), - center_y: LayoutAnchorY::center(anchor_view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(anchor_view), - #[cfg(feature = "appkit")] - scrollview: scrollview + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(anchor_view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(anchor_view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(anchor_view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(anchor_view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(anchor_view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(anchor_view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(anchor_view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(anchor_view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(anchor_view), + + scrollview }; (&mut delegate).did_load(view.clone_as_handle()); @@ -305,19 +360,38 @@ impl ListView { cell_factory: CellFactory::new(), menu: self.menu.clone(), delegate: None, - top: self.top.clone(), - leading: self.leading.clone(), - left: self.left.clone(), - trailing: self.trailing.clone(), - right: self.right.clone(), - bottom: self.bottom.clone(), - width: self.width.clone(), - height: self.height.clone(), - center_x: self.center_x.clone(), - center_y: self.center_y.clone(), objc: self.objc.clone(), - #[cfg(feature = "appkit")] + #[cfg(feature = "autolayout")] + top: self.top.clone(), + + #[cfg(feature = "autolayout")] + leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] + left: self.left.clone(), + + #[cfg(feature = "autolayout")] + trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] + right: self.right.clone(), + + #[cfg(feature = "autolayout")] + bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] + width: self.width.clone(), + + #[cfg(feature = "autolayout")] + height: self.height.clone(), + + #[cfg(feature = "autolayout")] + center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] + center_y: self.center_y.clone(), + scrollview: self.scrollview.clone_as_handle() } } diff --git a/src/listview/row/mod.rs b/src/listview/row/mod.rs index f6117ee..cdd567b 100644 --- a/src/listview/row/mod.rs +++ b/src/listview/row/mod.rs @@ -51,10 +51,13 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::color::Color; use crate::layer::Layer; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::view::ViewDelegate; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] mod appkit; @@ -74,6 +77,8 @@ pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "cacaoListViewRowDelegatePtr fn allocate_view(registration_fn: fn() -> *const Class) -> id { unsafe { let view: id = msg_send![registration_fn(), new]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -95,33 +100,43 @@ pub struct ListViewRow { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -138,17 +153,37 @@ impl ListViewRow { ListViewRow { delegate: None, - top: LayoutAnchorY::top(view), - left: LayoutAnchorX::left(view), - leading: LayoutAnchorX::leading(view), - right: LayoutAnchorX::right(view), - trailing: LayoutAnchorX::trailing(view), - bottom: LayoutAnchorY::bottom(view), - width: LayoutAnchorDimension::width(view), - height: LayoutAnchorDimension::height(view), - center_x: LayoutAnchorX::center(view), - center_y: LayoutAnchorY::center(view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(view), } } } @@ -175,17 +210,37 @@ impl ListViewRow where T: ViewDelegate + 'static { let view = ListViewRow { delegate: Some(delegate), - top: LayoutAnchorY::top(view), - left: LayoutAnchorX::left(view), - leading: LayoutAnchorX::leading(view), - right: LayoutAnchorX::right(view), - trailing: LayoutAnchorX::trailing(view), - bottom: LayoutAnchorY::bottom(view), - width: LayoutAnchorDimension::width(view), - height: LayoutAnchorDimension::height(view), - center_x: LayoutAnchorX::center(view), - center_y: LayoutAnchorY::center(view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(view), }; view @@ -201,25 +256,43 @@ impl ListViewRow where T: ViewDelegate + 'static { pub fn with_boxed(mut delegate: Box) -> ListViewRow { let view = allocate_view(register_listview_row_class_with_delegate::); unsafe { - //let view: id = msg_send![register_view_class_with_delegate::(), new]; - //let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let ptr: *const T = &*delegate; (&mut *view).set_ivar(LISTVIEW_ROW_DELEGATE_PTR, ptr as usize); }; let mut view = ListViewRow { delegate: None, - top: LayoutAnchorY::top(view), - left: LayoutAnchorX::left(view), - leading: LayoutAnchorX::leading(view), - right: LayoutAnchorX::right(view), - trailing: LayoutAnchorX::trailing(view), - bottom: LayoutAnchorY::bottom(view), - width: LayoutAnchorDimension::width(view), - height: LayoutAnchorDimension::height(view), - center_x: LayoutAnchorX::center(view), - center_y: LayoutAnchorY::center(view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(view), }; (&mut delegate).did_load(view.clone_as_handle()); @@ -237,17 +310,37 @@ impl ListViewRow where T: ViewDelegate + 'static { ListViewRow { delegate: None, + objc: self.objc.clone(), + + #[cfg(feature = "autolayout")] top: self.top.clone(), + + #[cfg(feature = "autolayout")] leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] left: self.left.clone(), + + #[cfg(feature = "autolayout")] trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] right: self.right.clone(), + + #[cfg(feature = "autolayout")] bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] width: self.width.clone(), + + #[cfg(feature = "autolayout")] height: self.height.clone(), + + #[cfg(feature = "autolayout")] center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] center_y: self.center_y.clone(), - objc: self.objc.clone() } } } @@ -262,17 +355,37 @@ impl ListViewRow { delegate: None, is_handle: true, layer: Layer::new(), + objc: self.objc.clone(), + + #[cfg(feature = "autolayout")] top: self.top.clone(), + + #[cfg(feature = "autolayout")] leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] left: self.left.clone(), + + #[cfg(feature = "autolayout")] trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] right: self.right.clone(), + + #[cfg(feature = "autolayout")] bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] width: self.width.clone(), + + #[cfg(feature = "autolayout")] height: self.height.clone(), + + #[cfg(feature = "autolayout")] center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] center_y: self.center_y.clone(), - objc: self.objc.clone() } } diff --git a/src/progress/mod.rs b/src/progress/mod.rs index 2341635..9f93c99 100644 --- a/src/progress/mod.rs +++ b/src/progress/mod.rs @@ -1,7 +1,7 @@ //! A progress indicator widget. //! -//! This control wraps `NSProgressIndicator` on macOS, and -//! `UIProgressView+UIActivityIndicatorView` on iOS and tvOS. It operates in two modes: determinate +//! This control wraps `NSProgressIndicator` in AppKit, and +//! `UIProgressView+UIActivityIndicatorView` in iOS/tvOS. It operates in two modes: determinate //! (where you have a fixed start and end) and indeterminate (infinite; it will go and go until you //! tell it to stop). //! @@ -19,9 +19,12 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSUInteger}; use crate::color::Color; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + mod enums; pub use enums::ProgressIndicatorStyle; @@ -32,33 +35,43 @@ pub struct ProgressIndicator { pub objc: ObjcProperty, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -75,6 +88,8 @@ impl ProgressIndicator { let view = unsafe { #[cfg(feature = "appkit")] let view: id = msg_send![class!(NSProgressIndicator), new]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -84,16 +99,36 @@ impl ProgressIndicator { }; ProgressIndicator { + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), } } diff --git a/src/scrollview/mod.rs b/src/scrollview/mod.rs index 25d2173..ea39bc8 100644 --- a/src/scrollview/mod.rs +++ b/src/scrollview/mod.rs @@ -47,10 +47,14 @@ use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::color::Color; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + +use crate::layout::Layout; use crate::pasteboard::PasteboardType; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] mod appkit; @@ -72,6 +76,8 @@ pub(crate) static SCROLLVIEW_DELEGATE_PTR: &str = "rstScrollViewDelegatePtr"; fn allocate_view(registration_fn: fn() -> *const Class) -> id { unsafe { let view: id = msg_send![registration_fn(), new]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -97,33 +103,43 @@ pub struct ScrollView { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -140,16 +156,37 @@ impl ScrollView { ScrollView { delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), } } @@ -169,16 +206,37 @@ impl ScrollView where T: ScrollViewDelegate + 'static { let mut view = ScrollView { delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), }; @@ -196,16 +254,37 @@ impl ScrollView { pub(crate) fn clone_as_handle(&self) -> ScrollView { ScrollView { delegate: None, + + #[cfg(feature = "autolayout")] top: self.top.clone(), + + #[cfg(feature = "autolayout")] leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] left: self.left.clone(), + + #[cfg(feature = "autolayout")] trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] right: self.right.clone(), + + #[cfg(feature = "autolayout")] bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] width: self.width.clone(), + + #[cfg(feature = "autolayout")] height: self.height.clone(), + + #[cfg(feature = "autolayout")] center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] center_y: self.center_y.clone(), + objc: self.objc.clone() } } diff --git a/src/switch.rs b/src/switch.rs index 33c9681..68985a6 100644 --- a/src/switch.rs +++ b/src/switch.rs @@ -11,9 +11,12 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, BOOL, YES, NO, NSString}; use crate::invoker::TargetActionHandler; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::utils::{load, properties::ObjcProperty}; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + /// A wrapper for `NSSwitch`. Holds (retains) pointers for the Objective-C runtime /// where our `NSSwitch` lives. #[derive(Debug)] @@ -23,33 +26,43 @@ pub struct Switch { handler: Option, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -62,24 +75,49 @@ impl Switch { let view: id = unsafe { let button: id = msg_send![register_class(), buttonWithTitle:title target:nil action:nil]; + + #[cfg(feature = "autolayout")] let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO]; + + #[cfg(feature = "appkit")] let _: () = msg_send![button, setButtonType:3]; + button }; Switch { handler: None, - top: LayoutAnchorY::top(view), - left: LayoutAnchorX::left(view), - leading: LayoutAnchorX::leading(view), - right: LayoutAnchorX::right(view), - trailing: LayoutAnchorX::trailing(view), - bottom: LayoutAnchorY::bottom(view), - width: LayoutAnchorDimension::width(view), - height: LayoutAnchorDimension::height(view), - center_x: LayoutAnchorX::center(view), - center_y: LayoutAnchorY::center(view), objc: ObjcProperty::retain(view), + + #[cfg(feature = "autolayout")] + top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] + left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] + leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] + right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] + trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] + bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] + width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] + height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] + center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] + center_y: LayoutAnchorY::center(view), } } diff --git a/src/text/label/mod.rs b/src/text/label/mod.rs index 8a154b1..251325f 100644 --- a/src/text/label/mod.rs +++ b/src/text/label/mod.rs @@ -46,10 +46,13 @@ use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSInteger, NSUInteger, NSString}; use crate::color::Color; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::text::{Font, TextAlign, LineBreakMode}; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] mod appkit; @@ -77,9 +80,10 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id { msg_send![registration_fn(), labelWithString:&*blank] }; - #[cfg(target_os = "ios")] + #[cfg(feature = "uikit")] let view: id = msg_send![registration_fn(), new]; + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -141,33 +145,43 @@ pub struct Label { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -184,16 +198,37 @@ impl Label { Label { delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), + objc: ObjcProperty::retain(view), } } @@ -207,24 +242,43 @@ impl Label where T: LabelDelegate + 'static { let label = allocate_view(register_view_class_with_delegate::); unsafe { - //let view: id = msg_send![register_view_class_with_delegate::(), new]; - //let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let ptr: *const T = &*delegate; (&mut *label).set_ivar(LABEL_DELEGATE_PTR, ptr as usize); }; let mut label = Label { delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(label), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(label), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(label), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(label), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(label), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(label), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(label), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(label), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(label), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(label), + objc: ObjcProperty::retain(label), }; @@ -242,16 +296,37 @@ impl Label { pub(crate) fn clone_as_handle(&self) -> Label { Label { delegate: None, + + #[cfg(feature = "autolayout")] top: self.top.clone(), + + #[cfg(feature = "autolayout")] leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] left: self.left.clone(), + + #[cfg(feature = "autolayout")] trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] right: self.right.clone(), + + #[cfg(feature = "autolayout")] bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] width: self.width.clone(), + + #[cfg(feature = "autolayout")] height: self.height.clone(), + + #[cfg(feature = "autolayout")] center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] center_y: self.center_y.clone(), + objc: self.objc.clone() } } diff --git a/src/view/mod.rs b/src/view/mod.rs index 3a420e7..c38fc8b 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -47,9 +47,12 @@ use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::color::Color; use crate::layer::Layer; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + #[cfg(feature = "appkit")] use crate::pasteboard::PasteboardType; @@ -70,6 +73,7 @@ pub use controller::ViewController; #[cfg(feature = "appkit")] mod splitviewcontroller; + #[cfg(feature = "appkit")] pub use splitviewcontroller::SplitViewController; @@ -100,33 +104,43 @@ pub struct View { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -145,6 +159,7 @@ impl View { /// so on. It returns a generic `View`, which the caller can then customize as needed. pub(crate) fn init(view: id) -> View { unsafe { + #[cfg(feature = "autolayout")] let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; #[cfg(feature = "appkit")] @@ -154,15 +169,35 @@ impl View { View { is_handle: false, delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), layer: Layer::wrap(unsafe { @@ -213,17 +248,37 @@ impl View { delegate: None, is_handle: true, layer: self.layer.clone(), + objc: self.objc.clone(), + + #[cfg(feature = "autolayout")] top: self.top.clone(), + + #[cfg(feature = "autolayout")] leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] left: self.left.clone(), + + #[cfg(feature = "autolayout")] trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] right: self.right.clone(), + + #[cfg(feature = "autolayout")] bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] width: self.width.clone(), + + #[cfg(feature = "autolayout")] height: self.height.clone(), + + #[cfg(feature = "autolayout")] center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] center_y: self.center_y.clone(), - objc: self.objc.clone() } } diff --git a/src/webview/mod.rs b/src/webview/mod.rs index 27252b6..1be9e62 100644 --- a/src/webview/mod.rs +++ b/src/webview/mod.rs @@ -21,10 +21,13 @@ use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, nil, YES, NO, NSString}; use crate::geometry::Rect; -use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; +use crate::layout::Layout; use crate::layer::Layer; use crate::utils::properties::ObjcProperty; +#[cfg(feature = "autolayout")] +use crate::layout::LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; + mod actions; pub use actions::*; @@ -82,6 +85,7 @@ fn allocate_webview( #[cfg(feature = "appkit")] let _: () = msg_send![webview, setWantsLayer:YES]; + #[cfg(feature = "autolayout")] let _: () = msg_send![webview, setTranslatesAutoresizingMaskIntoConstraints:NO]; if let Some(delegate) = &objc_delegate { @@ -113,33 +117,43 @@ pub struct WebView { pub delegate: Option>, /// A pointer to the Objective-C runtime top layout constraint. + #[cfg(feature = "autolayout")] pub top: LayoutAnchorY, /// A pointer to the Objective-C runtime leading layout constraint. + #[cfg(feature = "autolayout")] pub leading: LayoutAnchorX, /// A pointer to the Objective-C runtime left layout constraint. + #[cfg(feature = "autolayout")] pub left: LayoutAnchorX, /// A pointer to the Objective-C runtime trailing layout constraint. + #[cfg(feature = "autolayout")] pub trailing: LayoutAnchorX, /// A pointer to the Objective-C runtime right layout constraint. + #[cfg(feature = "autolayout")] pub right: LayoutAnchorX, /// A pointer to the Objective-C runtime bottom layout constraint. + #[cfg(feature = "autolayout")] pub bottom: LayoutAnchorY, /// A pointer to the Objective-C runtime width layout constraint. + #[cfg(feature = "autolayout")] pub width: LayoutAnchorDimension, /// A pointer to the Objective-C runtime height layout constraint. + #[cfg(feature = "autolayout")] pub height: LayoutAnchorDimension, /// A pointer to the Objective-C runtime center X layout constraint. + #[cfg(feature = "autolayout")] pub center_x: LayoutAnchorX, /// A pointer to the Objective-C runtime center Y layout constraint. + #[cfg(feature = "autolayout")] pub center_y: LayoutAnchorY } @@ -167,15 +181,35 @@ impl WebView { is_handle: false, delegate: None, objc_delegate: None, + + #[cfg(feature = "autolayout")] top: LayoutAnchorY::top(view), + + #[cfg(feature = "autolayout")] left: LayoutAnchorX::left(view), + + #[cfg(feature = "autolayout")] leading: LayoutAnchorX::leading(view), + + #[cfg(feature = "autolayout")] right: LayoutAnchorX::right(view), + + #[cfg(feature = "autolayout")] trailing: LayoutAnchorX::trailing(view), + + #[cfg(feature = "autolayout")] bottom: LayoutAnchorY::bottom(view), + + #[cfg(feature = "autolayout")] width: LayoutAnchorDimension::width(view), + + #[cfg(feature = "autolayout")] height: LayoutAnchorDimension::height(view), + + #[cfg(feature = "autolayout")] center_x: LayoutAnchorX::center(view), + + #[cfg(feature = "autolayout")] center_y: LayoutAnchorY::center(view), layer: Layer::wrap(unsafe { @@ -224,20 +258,40 @@ impl WebView { pub(crate) fn clone_as_handle(&self) -> WebView { WebView { delegate: None, - top: self.top.clone(), - leading: self.leading.clone(), - left: self.left.clone(), - right: self.right.clone(), is_handle: true, - trailing: self.trailing.clone(), - bottom: self.bottom.clone(), - width: self.width.clone(), - height: self.height.clone(), - center_x: self.center_x.clone(), - center_y: self.center_y.clone(), layer: self.layer.clone(), objc: self.objc.clone(), - objc_delegate: None + objc_delegate: None, + + #[cfg(feature = "autolayout")] + top: self.top.clone(), + + #[cfg(feature = "autolayout")] + leading: self.leading.clone(), + + #[cfg(feature = "autolayout")] + left: self.left.clone(), + + #[cfg(feature = "autolayout")] + right: self.right.clone(), + + #[cfg(feature = "autolayout")] + trailing: self.trailing.clone(), + + #[cfg(feature = "autolayout")] + bottom: self.bottom.clone(), + + #[cfg(feature = "autolayout")] + width: self.width.clone(), + + #[cfg(feature = "autolayout")] + height: self.height.clone(), + + #[cfg(feature = "autolayout")] + center_x: self.center_x.clone(), + + #[cfg(feature = "autolayout")] + center_y: self.center_y.clone() } }