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.
This commit is contained in:
Ryan McGrath 2021-08-08 18:42:07 -07:00
parent c713194262
commit 93424f74c0
No known key found for this signature in database
GPG key ID: DA6CBD9233593DEA
19 changed files with 1012 additions and 148 deletions

View file

@ -38,7 +38,8 @@ eval = "0.4"
[features] [features]
appkit = ["core-foundation/mac_os_10_8_features"] appkit = ["core-foundation/mac_os_10_8_features"]
uikit = [] uikit = []
default = ["appkit"] autolayout = []
default = ["appkit", "autolayout"]
cloudkit = [] cloudkit = []
color_fallbacks = [] color_fallbacks = []
quicklook = [] quicklook = []

115
examples/frame_layout.rs Normal file
View file

@ -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<AppWindow>
}
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();
}

View file

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

64
examples/readme.md Normal file
View file

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

View file

@ -32,10 +32,13 @@ use crate::color::Color;
use crate::image::Image; use crate::image::Image;
use crate::foundation::{id, nil, BOOL, YES, NO, NSString, NSUInteger}; use crate::foundation::{id, nil, BOOL, YES, NO, NSString, NSUInteger};
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::text::{AttributedString, Font}; use crate::text::{AttributedString, Font};
use crate::utils::{load, properties::ObjcProperty}; use crate::utils::{load, properties::ObjcProperty};
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
use crate::appkit::FocusRingType; use crate::appkit::FocusRingType;
@ -71,33 +74,43 @@ pub struct Button {
handler: Option<TargetActionHandler>, handler: Option<TargetActionHandler>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -114,23 +127,47 @@ impl Button {
]; ];
let _: () = msg_send![button, setWantsLayer:YES]; let _: () = msg_send![button, setWantsLayer:YES];
#[cfg(feature = "autolayout")]
let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO];
button button
}; };
Button { Button {
handler: None, handler: None,
image: None, image: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
} }
} }

View file

@ -39,7 +39,7 @@ impl Rect {
impl From<Rect> for CGRect { impl From<Rect> for CGRect {
fn from(rect: Rect) -> CGRect { fn from(rect: Rect) -> CGRect {
CGRect::new( CGRect::new(
&CGPoint::new(rect.top, rect.left), &CGPoint::new(rect.left, rect.top),
&CGSize::new(rect.width, rect.height) &CGSize::new(rect.width, rect.height)
) )
} }

View file

@ -4,9 +4,12 @@ use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod appkit; mod appkit;
@ -29,6 +32,8 @@ pub use icons::*;
fn allocate_view(registration_fn: fn() -> *const Class) -> id { fn allocate_view(registration_fn: fn() -> *const Class) -> id {
unsafe { unsafe {
let view: id = msg_send![registration_fn(), new]; let view: id = msg_send![registration_fn(), new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -47,33 +52,43 @@ pub struct ImageView {
pub objc: ObjcProperty, pub objc: ObjcProperty,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -89,16 +104,36 @@ impl ImageView {
let view = allocate_view(register_image_view_class); let view = allocate_view(register_image_view_class);
ImageView { ImageView {
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
} }
} }

View file

@ -46,10 +46,13 @@ use objc_id::ShareId;
use crate::color::Color; use crate::color::Color;
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NO, YES}; 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::text::{Font, TextAlign};
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod appkit; mod appkit;
@ -72,6 +75,7 @@ fn common_init(class: *const Class) -> id {
unsafe { unsafe {
let view: id = msg_send![class, new]; let view: id = msg_send![class, new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -92,33 +96,43 @@ pub struct TextField<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY, pub center_y: LayoutAnchorY,
} }
@ -136,17 +150,37 @@ impl TextField {
TextField { TextField {
delegate: None, 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), 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 { let mut label = TextField {
delegate: None, 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), 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()); (&mut delegate).did_load(label.clone_as_handle());
@ -196,17 +250,37 @@ impl<T> TextField<T> {
pub(crate) fn clone_as_handle(&self) -> TextField { pub(crate) fn clone_as_handle(&self) -> TextField {
TextField { TextField {
delegate: None, 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(), 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(),
} }
} }

View file

@ -1,26 +1,37 @@
//! A wrapper for `NSLayoutConstraint`, enabling AutoLayout across views. This does a few things //! This module contains traits and helpers for layout. By default, standard frame-based layouts
//! that might seem weird, but are generally good and rely on the idea that this is all written //! are supported via the `Layout` trait, which all widgets implement. If you opt in to the
//! once and used often. //! `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.
//! 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::*;
pub mod traits; pub mod traits;
pub use traits::Layout; pub use traits::Layout;
#[cfg(feature = "autolayout")]
pub mod attributes;
#[cfg(feature = "autolayout")]
pub use attributes::*;
#[cfg(feature = "autolayout")]
pub mod constraint; pub mod constraint;
#[cfg(feature = "autolayout")]
pub use constraint::LayoutConstraint; pub use constraint::LayoutConstraint;
#[cfg(feature = "autolayout")]
pub mod dimension; pub mod dimension;
#[cfg(feature = "autolayout")]
pub use dimension::LayoutAnchorDimension; pub use dimension::LayoutAnchorDimension;
#[cfg(feature = "autolayout")]
pub mod horizontal; pub mod horizontal;
#[cfg(feature = "autolayout")]
pub use horizontal::LayoutAnchorX; pub use horizontal::LayoutAnchorX;
#[cfg(feature = "autolayout")]
pub mod vertical; pub mod vertical;
#[cfg(feature = "autolayout")]
pub use vertical::LayoutAnchorY; pub use vertical::LayoutAnchorY;

View file

@ -71,6 +71,7 @@ pub trait Layout {
/// ///
/// Cacao defaults this to `false`; if you need to set frame-based layout pieces, /// 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). /// 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) { fn set_translates_autoresizing_mask_into_constraints(&self, translates: bool) {
self.with_backing_node(|backing_node| unsafe { self.with_backing_node(|backing_node| unsafe {
let _: () = msg_send![backing_node, setTranslatesAutoresizingMaskIntoConstraints:match translates { let _: () = msg_send![backing_node, setTranslatesAutoresizingMaskIntoConstraints:match translates {

View file

@ -96,6 +96,9 @@ pub use objc;
pub use url; pub use url;
pub use lazy_static; 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(feature = "appkit")]
#[cfg_attr(docsrs, doc(cfg(target_os = "appkit")))] #[cfg_attr(docsrs, doc(cfg(target_os = "appkit")))]
pub mod appkit; pub mod appkit;

View file

@ -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::foundation::{id, nil, YES, NO, NSArray, NSString, NSInteger, NSUInteger};
use crate::color::Color; 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::scrollview::ScrollView;
use crate::utils::{os, CellFactory, CGSize}; use crate::utils::{os, CellFactory, CGSize};
use crate::utils::properties::{ObjcProperty, PropertyNullable}; use crate::utils::properties::{ObjcProperty, PropertyNullable};
@ -95,6 +100,8 @@ use std::cell::RefCell;
fn common_init(class: *const Class) -> id { fn common_init(class: *const Class) -> id {
unsafe { unsafe {
let tableview: id = msg_send![class, new]; let tableview: id = msg_send![class, new];
#[cfg(feature = "autolayout")]
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.
@ -139,40 +146,51 @@ pub struct ListView<T = ()> {
/// In AppKit, 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(feature = "appkit")] ///
/// In iOS, this is a pointer to the UITableView-owned UIScrollView.
pub scrollview: ScrollView, pub scrollview: ScrollView,
/// A pointer to the delegate for this view. /// A pointer to the delegate for this view.
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -201,32 +219,52 @@ impl ListView {
// For AppKit, 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(feature = "appkit")] #[cfg(all(feature = "appkit", feature = "autolayout"))]
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(all(feature = "uikit", feature = "autolayout"))]
let anchor_view: id = view; //let anchor_view: id = view;
ListView { ListView {
cell_factory: CellFactory::new(), cell_factory: CellFactory::new(),
menu: PropertyNullable::default(), menu: PropertyNullable::default(),
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(anchor_view), top: LayoutAnchorY::top(anchor_view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(anchor_view), left: LayoutAnchorX::left(anchor_view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(anchor_view), leading: LayoutAnchorX::leading(anchor_view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(anchor_view), right: LayoutAnchorX::right(anchor_view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(anchor_view), trailing: LayoutAnchorX::trailing(anchor_view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(anchor_view), bottom: LayoutAnchorY::bottom(anchor_view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(anchor_view), width: LayoutAnchorDimension::width(anchor_view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(anchor_view), height: LayoutAnchorDimension::height(anchor_view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(anchor_view), center_x: LayoutAnchorX::center(anchor_view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(anchor_view), center_y: LayoutAnchorY::center(anchor_view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
#[cfg(feature = "appkit")] scrollview
scrollview: scrollview
} }
} }
} }
@ -241,8 +279,6 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
let cell = CellFactory::new(); let cell = CellFactory::new();
unsafe { unsafe {
//let view: id = msg_send![register_view_class_with_delegate::<T>(), new];
//let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
let delegate_ptr: *const T = &*delegate; let delegate_ptr: *const T = &*delegate;
(&mut *view).set_ivar(LISTVIEW_DELEGATE_PTR, delegate_ptr as usize); (&mut *view).set_ivar(LISTVIEW_DELEGATE_PTR, delegate_ptr as usize);
let _: () = msg_send![view, setDelegate:view]; let _: () = msg_send![view, setDelegate:view];
@ -261,7 +297,7 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
}; };
// For AppKit, 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(feature = "appkit")] #[cfg(all(feature = "appkit", feature = "autolayout"))]
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]
}); });
@ -273,20 +309,39 @@ impl<T> ListView<T> where T: ListViewDelegate + 'static {
cell_factory: cell, cell_factory: cell,
menu: PropertyNullable::default(), menu: PropertyNullable::default(),
delegate: None, 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), objc: ObjcProperty::retain(view),
#[cfg(feature = "appkit")] #[cfg(feature = "autolayout")]
scrollview: scrollview 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),
scrollview
}; };
(&mut delegate).did_load(view.clone_as_handle()); (&mut delegate).did_load(view.clone_as_handle());
@ -305,19 +360,38 @@ impl<T> ListView<T> {
cell_factory: CellFactory::new(), cell_factory: CellFactory::new(),
menu: self.menu.clone(), menu: self.menu.clone(),
delegate: None, 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(), 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() scrollview: self.scrollview.clone_as_handle()
} }
} }

View file

@ -51,10 +51,13 @@ use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::layer::Layer; use crate::layer::Layer;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::view::ViewDelegate; use crate::view::ViewDelegate;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod 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 { fn allocate_view(registration_fn: fn() -> *const Class) -> id {
unsafe { unsafe {
let view: id = msg_send![registration_fn(), new]; let view: id = msg_send![registration_fn(), new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -95,33 +100,43 @@ pub struct ListViewRow<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -138,17 +153,37 @@ impl ListViewRow {
ListViewRow { ListViewRow {
delegate: None, 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), 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<T> ListViewRow<T> where T: ViewDelegate + 'static {
let view = ListViewRow { let view = ListViewRow {
delegate: Some(delegate), 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), 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 view
@ -201,25 +256,43 @@ impl<T> ListViewRow<T> where T: ViewDelegate + 'static {
pub fn with_boxed(mut delegate: Box<T>) -> ListViewRow<T> { pub fn with_boxed(mut delegate: Box<T>) -> ListViewRow<T> {
let view = allocate_view(register_listview_row_class_with_delegate::<T>); let view = allocate_view(register_listview_row_class_with_delegate::<T>);
unsafe { unsafe {
//let view: id = msg_send![register_view_class_with_delegate::<T>(), new];
//let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
let ptr: *const T = &*delegate; let ptr: *const T = &*delegate;
(&mut *view).set_ivar(LISTVIEW_ROW_DELEGATE_PTR, ptr as usize); (&mut *view).set_ivar(LISTVIEW_ROW_DELEGATE_PTR, ptr as usize);
}; };
let mut view = ListViewRow { let mut view = ListViewRow {
delegate: None, 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), 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()); (&mut delegate).did_load(view.clone_as_handle());
@ -237,17 +310,37 @@ impl<T> ListViewRow<T> where T: ViewDelegate + 'static {
ListViewRow { ListViewRow {
delegate: None, delegate: None,
objc: self.objc.clone(),
#[cfg(feature = "autolayout")]
top: self.top.clone(), top: self.top.clone(),
#[cfg(feature = "autolayout")]
leading: self.leading.clone(), leading: self.leading.clone(),
#[cfg(feature = "autolayout")]
left: self.left.clone(), left: self.left.clone(),
#[cfg(feature = "autolayout")]
trailing: self.trailing.clone(), trailing: self.trailing.clone(),
#[cfg(feature = "autolayout")]
right: self.right.clone(), right: self.right.clone(),
#[cfg(feature = "autolayout")]
bottom: self.bottom.clone(), bottom: self.bottom.clone(),
#[cfg(feature = "autolayout")]
width: self.width.clone(), width: self.width.clone(),
#[cfg(feature = "autolayout")]
height: self.height.clone(), height: self.height.clone(),
#[cfg(feature = "autolayout")]
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone(),
objc: self.objc.clone()
} }
} }
} }
@ -262,17 +355,37 @@ impl<T> ListViewRow<T> {
delegate: None, delegate: None,
is_handle: true, is_handle: true,
layer: Layer::new(), layer: Layer::new(),
objc: self.objc.clone(),
#[cfg(feature = "autolayout")]
top: self.top.clone(), top: self.top.clone(),
#[cfg(feature = "autolayout")]
leading: self.leading.clone(), leading: self.leading.clone(),
#[cfg(feature = "autolayout")]
left: self.left.clone(), left: self.left.clone(),
#[cfg(feature = "autolayout")]
trailing: self.trailing.clone(), trailing: self.trailing.clone(),
#[cfg(feature = "autolayout")]
right: self.right.clone(), right: self.right.clone(),
#[cfg(feature = "autolayout")]
bottom: self.bottom.clone(), bottom: self.bottom.clone(),
#[cfg(feature = "autolayout")]
width: self.width.clone(), width: self.width.clone(),
#[cfg(feature = "autolayout")]
height: self.height.clone(), height: self.height.clone(),
#[cfg(feature = "autolayout")]
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone(),
objc: self.objc.clone()
} }
} }

View file

@ -1,7 +1,7 @@
//! A progress indicator widget. //! A progress indicator widget.
//! //!
//! This control wraps `NSProgressIndicator` on macOS, and //! This control wraps `NSProgressIndicator` in AppKit, and
//! `UIProgressView+UIActivityIndicatorView` on iOS and tvOS. It operates in two modes: determinate //! `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 //! (where you have a fixed start and end) and indeterminate (infinite; it will go and go until you
//! tell it to stop). //! 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::foundation::{id, nil, YES, NO, NSUInteger};
use crate::color::Color; use crate::color::Color;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
mod enums; mod enums;
pub use enums::ProgressIndicatorStyle; pub use enums::ProgressIndicatorStyle;
@ -32,33 +35,43 @@ pub struct ProgressIndicator {
pub objc: ObjcProperty, pub objc: ObjcProperty,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -75,6 +88,8 @@ impl ProgressIndicator {
let view = unsafe { let view = unsafe {
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
let view: id = msg_send![class!(NSProgressIndicator), new]; let view: id = msg_send![class!(NSProgressIndicator), new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -84,16 +99,36 @@ impl ProgressIndicator {
}; };
ProgressIndicator { ProgressIndicator {
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
} }
} }

View file

@ -47,10 +47,14 @@ use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
use crate::layout::Layout;
use crate::pasteboard::PasteboardType; use crate::pasteboard::PasteboardType;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod appkit; mod appkit;
@ -72,6 +76,8 @@ pub(crate) static SCROLLVIEW_DELEGATE_PTR: &str = "rstScrollViewDelegatePtr";
fn allocate_view(registration_fn: fn() -> *const Class) -> id { fn allocate_view(registration_fn: fn() -> *const Class) -> id {
unsafe { unsafe {
let view: id = msg_send![registration_fn(), new]; let view: id = msg_send![registration_fn(), new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -97,33 +103,43 @@ pub struct ScrollView<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -140,16 +156,37 @@ impl ScrollView {
ScrollView { ScrollView {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
} }
} }
@ -169,16 +206,37 @@ impl<T> ScrollView<T> where T: ScrollViewDelegate + 'static {
let mut view = ScrollView { let mut view = ScrollView {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
}; };
@ -196,16 +254,37 @@ impl<T> ScrollView<T> {
pub(crate) fn clone_as_handle(&self) -> ScrollView { pub(crate) fn clone_as_handle(&self) -> ScrollView {
ScrollView { ScrollView {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: self.top.clone(), top: self.top.clone(),
#[cfg(feature = "autolayout")]
leading: self.leading.clone(), leading: self.leading.clone(),
#[cfg(feature = "autolayout")]
left: self.left.clone(), left: self.left.clone(),
#[cfg(feature = "autolayout")]
trailing: self.trailing.clone(), trailing: self.trailing.clone(),
#[cfg(feature = "autolayout")]
right: self.right.clone(), right: self.right.clone(),
#[cfg(feature = "autolayout")]
bottom: self.bottom.clone(), bottom: self.bottom.clone(),
#[cfg(feature = "autolayout")]
width: self.width.clone(), width: self.width.clone(),
#[cfg(feature = "autolayout")]
height: self.height.clone(), height: self.height.clone(),
#[cfg(feature = "autolayout")]
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone(),
objc: self.objc.clone() objc: self.objc.clone()
} }
} }

View file

@ -11,9 +11,12 @@ use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, BOOL, YES, NO, NSString}; use crate::foundation::{id, nil, BOOL, YES, NO, NSString};
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::utils::{load, properties::ObjcProperty}; 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 /// A wrapper for `NSSwitch`. Holds (retains) pointers for the Objective-C runtime
/// where our `NSSwitch` lives. /// where our `NSSwitch` lives.
#[derive(Debug)] #[derive(Debug)]
@ -23,33 +26,43 @@ pub struct Switch {
handler: Option<TargetActionHandler>, handler: Option<TargetActionHandler>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -62,24 +75,49 @@ impl Switch {
let view: id = unsafe { let view: id = unsafe {
let button: id = msg_send![register_class(), buttonWithTitle:title target:nil action:nil]; let button: id = msg_send![register_class(), buttonWithTitle:title target:nil action:nil];
#[cfg(feature = "autolayout")]
let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")]
let _: () = msg_send![button, setButtonType:3]; let _: () = msg_send![button, setButtonType:3];
button button
}; };
Switch { Switch {
handler: None, 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), 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 file

@ -46,10 +46,13 @@ use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSArray, NSInteger, NSUInteger, NSString}; use crate::foundation::{id, nil, YES, NO, NSArray, NSInteger, NSUInteger, NSString};
use crate::color::Color; use crate::color::Color;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::text::{Font, TextAlign, LineBreakMode}; use crate::text::{Font, TextAlign, LineBreakMode};
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod appkit; mod appkit;
@ -77,9 +80,10 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id {
msg_send![registration_fn(), labelWithString:&*blank] msg_send![registration_fn(), labelWithString:&*blank]
}; };
#[cfg(target_os = "ios")] #[cfg(feature = "uikit")]
let view: id = msg_send![registration_fn(), new]; let view: id = msg_send![registration_fn(), new];
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -141,33 +145,43 @@ pub struct Label<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -184,16 +198,37 @@ impl Label {
Label { Label {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view),
} }
} }
@ -207,24 +242,43 @@ impl<T> Label<T> where T: LabelDelegate + 'static {
let label = allocate_view(register_view_class_with_delegate::<T>); let label = allocate_view(register_view_class_with_delegate::<T>);
unsafe { unsafe {
//let view: id = msg_send![register_view_class_with_delegate::<T>(), new];
//let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
let ptr: *const T = &*delegate; let ptr: *const T = &*delegate;
(&mut *label).set_ivar(LABEL_DELEGATE_PTR, ptr as usize); (&mut *label).set_ivar(LABEL_DELEGATE_PTR, ptr as usize);
}; };
let mut label = Label { let mut label = Label {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(label), top: LayoutAnchorY::top(label),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(label), left: LayoutAnchorX::left(label),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(label), leading: LayoutAnchorX::leading(label),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(label), right: LayoutAnchorX::right(label),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(label), trailing: LayoutAnchorX::trailing(label),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(label), bottom: LayoutAnchorY::bottom(label),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(label), width: LayoutAnchorDimension::width(label),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(label), height: LayoutAnchorDimension::height(label),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(label), center_x: LayoutAnchorX::center(label),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(label), center_y: LayoutAnchorY::center(label),
objc: ObjcProperty::retain(label), objc: ObjcProperty::retain(label),
}; };
@ -242,16 +296,37 @@ impl<T> Label<T> {
pub(crate) fn clone_as_handle(&self) -> Label { pub(crate) fn clone_as_handle(&self) -> Label {
Label { Label {
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: self.top.clone(), top: self.top.clone(),
#[cfg(feature = "autolayout")]
leading: self.leading.clone(), leading: self.leading.clone(),
#[cfg(feature = "autolayout")]
left: self.left.clone(), left: self.left.clone(),
#[cfg(feature = "autolayout")]
trailing: self.trailing.clone(), trailing: self.trailing.clone(),
#[cfg(feature = "autolayout")]
right: self.right.clone(), right: self.right.clone(),
#[cfg(feature = "autolayout")]
bottom: self.bottom.clone(), bottom: self.bottom.clone(),
#[cfg(feature = "autolayout")]
width: self.width.clone(), width: self.width.clone(),
#[cfg(feature = "autolayout")]
height: self.height.clone(), height: self.height.clone(),
#[cfg(feature = "autolayout")]
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone(),
objc: self.objc.clone() objc: self.objc.clone()
} }
} }

View file

@ -47,9 +47,12 @@ use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSArray, NSString}; use crate::foundation::{id, nil, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::layer::Layer; use crate::layer::Layer;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
use crate::pasteboard::PasteboardType; use crate::pasteboard::PasteboardType;
@ -70,6 +73,7 @@ pub use controller::ViewController;
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod splitviewcontroller; mod splitviewcontroller;
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
pub use splitviewcontroller::SplitViewController; pub use splitviewcontroller::SplitViewController;
@ -100,33 +104,43 @@ pub struct View<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -145,6 +159,7 @@ impl View {
/// so on. It returns a generic `View<T>`, which the caller can then customize as needed. /// so on. It returns a generic `View<T>`, which the caller can then customize as needed.
pub(crate) fn init<T>(view: id) -> View<T> { pub(crate) fn init<T>(view: id) -> View<T> {
unsafe { unsafe {
#[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
@ -154,15 +169,35 @@ impl View {
View { View {
is_handle: false, is_handle: false,
delegate: None, delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
layer: Layer::wrap(unsafe { layer: Layer::wrap(unsafe {
@ -213,17 +248,37 @@ impl<T> View<T> {
delegate: None, delegate: None,
is_handle: true, is_handle: true,
layer: self.layer.clone(), layer: self.layer.clone(),
objc: self.objc.clone(),
#[cfg(feature = "autolayout")]
top: self.top.clone(), top: self.top.clone(),
#[cfg(feature = "autolayout")]
leading: self.leading.clone(), leading: self.leading.clone(),
#[cfg(feature = "autolayout")]
left: self.left.clone(), left: self.left.clone(),
#[cfg(feature = "autolayout")]
trailing: self.trailing.clone(), trailing: self.trailing.clone(),
#[cfg(feature = "autolayout")]
right: self.right.clone(), right: self.right.clone(),
#[cfg(feature = "autolayout")]
bottom: self.bottom.clone(), bottom: self.bottom.clone(),
#[cfg(feature = "autolayout")]
width: self.width.clone(), width: self.width.clone(),
#[cfg(feature = "autolayout")]
height: self.height.clone(), height: self.height.clone(),
#[cfg(feature = "autolayout")]
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone(),
objc: self.objc.clone()
} }
} }

View file

@ -21,10 +21,13 @@ use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSString}; use crate::foundation::{id, nil, YES, NO, NSString};
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::Layout;
use crate::layer::Layer; use crate::layer::Layer;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")]
use crate::layout::LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
mod actions; mod actions;
pub use actions::*; pub use actions::*;
@ -82,6 +85,7 @@ fn allocate_webview(
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
let _: () = msg_send![webview, setWantsLayer:YES]; let _: () = msg_send![webview, setWantsLayer:YES];
#[cfg(feature = "autolayout")]
let _: () = msg_send![webview, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![webview, setTranslatesAutoresizingMaskIntoConstraints:NO];
if let Some(delegate) = &objc_delegate { if let Some(delegate) = &objc_delegate {
@ -113,33 +117,43 @@ pub struct WebView<T = ()> {
pub delegate: Option<Box<T>>, pub delegate: Option<Box<T>>,
/// A pointer to the Objective-C runtime top layout constraint. /// A pointer to the Objective-C runtime top layout constraint.
#[cfg(feature = "autolayout")]
pub top: LayoutAnchorY, pub top: LayoutAnchorY,
/// A pointer to the Objective-C runtime leading layout constraint. /// A pointer to the Objective-C runtime leading layout constraint.
#[cfg(feature = "autolayout")]
pub leading: LayoutAnchorX, pub leading: LayoutAnchorX,
/// A pointer to the Objective-C runtime left layout constraint. /// A pointer to the Objective-C runtime left layout constraint.
#[cfg(feature = "autolayout")]
pub left: LayoutAnchorX, pub left: LayoutAnchorX,
/// A pointer to the Objective-C runtime trailing layout constraint. /// A pointer to the Objective-C runtime trailing layout constraint.
#[cfg(feature = "autolayout")]
pub trailing: LayoutAnchorX, pub trailing: LayoutAnchorX,
/// A pointer to the Objective-C runtime right layout constraint. /// A pointer to the Objective-C runtime right layout constraint.
#[cfg(feature = "autolayout")]
pub right: LayoutAnchorX, pub right: LayoutAnchorX,
/// A pointer to the Objective-C runtime bottom layout constraint. /// A pointer to the Objective-C runtime bottom layout constraint.
#[cfg(feature = "autolayout")]
pub bottom: LayoutAnchorY, pub bottom: LayoutAnchorY,
/// A pointer to the Objective-C runtime width layout constraint. /// A pointer to the Objective-C runtime width layout constraint.
#[cfg(feature = "autolayout")]
pub width: LayoutAnchorDimension, pub width: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime height layout constraint. /// A pointer to the Objective-C runtime height layout constraint.
#[cfg(feature = "autolayout")]
pub height: LayoutAnchorDimension, pub height: LayoutAnchorDimension,
/// A pointer to the Objective-C runtime center X layout constraint. /// A pointer to the Objective-C runtime center X layout constraint.
#[cfg(feature = "autolayout")]
pub center_x: LayoutAnchorX, pub center_x: LayoutAnchorX,
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY pub center_y: LayoutAnchorY
} }
@ -167,15 +181,35 @@ impl WebView {
is_handle: false, is_handle: false,
delegate: None, delegate: None,
objc_delegate: None, objc_delegate: None,
#[cfg(feature = "autolayout")]
top: LayoutAnchorY::top(view), top: LayoutAnchorY::top(view),
#[cfg(feature = "autolayout")]
left: LayoutAnchorX::left(view), left: LayoutAnchorX::left(view),
#[cfg(feature = "autolayout")]
leading: LayoutAnchorX::leading(view), leading: LayoutAnchorX::leading(view),
#[cfg(feature = "autolayout")]
right: LayoutAnchorX::right(view), right: LayoutAnchorX::right(view),
#[cfg(feature = "autolayout")]
trailing: LayoutAnchorX::trailing(view), trailing: LayoutAnchorX::trailing(view),
#[cfg(feature = "autolayout")]
bottom: LayoutAnchorY::bottom(view), bottom: LayoutAnchorY::bottom(view),
#[cfg(feature = "autolayout")]
width: LayoutAnchorDimension::width(view), width: LayoutAnchorDimension::width(view),
#[cfg(feature = "autolayout")]
height: LayoutAnchorDimension::height(view), height: LayoutAnchorDimension::height(view),
#[cfg(feature = "autolayout")]
center_x: LayoutAnchorX::center(view), center_x: LayoutAnchorX::center(view),
#[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
layer: Layer::wrap(unsafe { layer: Layer::wrap(unsafe {
@ -224,20 +258,40 @@ impl<T> WebView<T> {
pub(crate) fn clone_as_handle(&self) -> WebView { pub(crate) fn clone_as_handle(&self) -> WebView {
WebView { WebView {
delegate: None, delegate: None,
top: self.top.clone(),
leading: self.leading.clone(),
left: self.left.clone(),
right: self.right.clone(),
is_handle: true, 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(), layer: self.layer.clone(),
objc: self.objc.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()
} }
} }