diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d088639..903dcbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,3 +70,32 @@ jobs: command: build target: x86_64-apple-ios args: --example ios-beta --no-default-features --features uikit,autolayout + + ios: + name: Check that examples build + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + target: x86_64-apple-ios + - uses: actions-rs/install@v0.1 + with: + crate: cargo-dinghy + version: latest + use-tool-cache: true + + - name: Launch XCode Simulator and prepare Dinghy + run: | + # Get system info + xcrun simctl list runtimes + # Launch the simulator + RUNTIME_ID=$(xcrun simctl list runtimes | grep iOS | cut -d ' ' -f 7 | tail -1) + SIM_ID=$(xcrun simctl create My-iphone7 com.apple.CoreSimulator.SimDeviceType.iPhone-SE-3rd-generation $RUNTIME_ID) + xcrun simctl boot $SIM_ID + + - name: Dinghy test + run: | + cargo dinghy --platform auto-ios-x86_64 test --no-default-features --features uikit,autolayout diff --git a/Cargo.toml b/Cargo.toml index 20c78b5..b97c6dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,3 +65,37 @@ required-features = ["webview"] [[example]] name = "ios-beta" required-features = ["uikit", "autolayout"] + +[[example]] +name = "calculator" +required-features = ["appkit"] +[[example]] +name = "todos_list" +required-features = ["appkit"] +[[example]] +name = "animation" +required-features = ["appkit"] +[[example]] +name = "autolayout" +required-features = ["appkit"] +[[example]] +name = "custom_image_drawing" +required-features = ["appkit"] +[[example]] +name = "text_input" +required-features = ["appkit"] +[[example]] +name = "defaults" +required-features = ["appkit"] +[[example]] +name = "frame_layout" +required-features = ["appkit"] +[[example]] +name = "window" +required-features = ["appkit"] +[[example]] +name = "window_delegate" +required-features = ["appkit"] +[[example]] +name = "window_controller" +required-features = ["appkit"] diff --git a/examples/ios-beta/main.rs b/examples/ios-beta/main.rs index 656f258..c2f88c0 100644 --- a/examples/ios-beta/main.rs +++ b/examples/ios-beta/main.rs @@ -5,6 +5,7 @@ use cacao::uikit::{App, AppDelegate, Scene, SceneConfig, SceneConnectionOptions, use cacao::color::Color; use cacao::layout::{Layout, LayoutConstraint}; use cacao::view::{View, ViewController, ViewDelegate}; +use cacao::image::{ImageView, Image}; #[derive(Default)] struct TestApp; @@ -19,7 +20,8 @@ impl AppDelegate for TestApp { pub struct RootView { pub red: View, pub green: View, - pub blue: View + pub blue: View, + pub image: ImageView, } impl ViewDelegate for RootView { @@ -36,6 +38,11 @@ impl ViewDelegate for RootView { self.blue.set_background_color(Color::SystemBlue); view.add_subview(&self.blue); + let image_bytes = include_bytes!("../../test-data/favicon.ico"); + self.image = ImageView::new(); + self.image.set_image(&Image::with_data(image_bytes)); + view.add_subview(&self.image); + LayoutConstraint::activate(&[ self.red.top.constraint_equal_to(&view.top).offset(16.), self.red.leading.constraint_equal_to(&view.leading).offset(16.), diff --git a/src/image/image.rs b/src/image/image.rs index 3aeba50..2272c3e 100644 --- a/src/image/image.rs +++ b/src/image/image.rs @@ -1,4 +1,4 @@ -use objc::runtime::Object; +use objc::runtime::{Object, Class}; use objc_id::ShareId; use objc::{class, msg_send, sel, sel_impl}; @@ -122,6 +122,15 @@ pub struct DrawConfig { pub struct Image(pub ShareId); impl Image { + fn class() -> &'static Class { + #[cfg(feature = "appkit")] + let class = class!(NSImage); + #[cfg(all(feature = "uikit", not(feature = "appkit")))] + let class = class!(UIImage); + + class + } + /// Wraps a system-returned image, e.g from QuickLook previews. pub fn with(image: id) -> Self { Image(unsafe { ShareId::from_ptr(image) }) @@ -143,7 +152,7 @@ impl Image { let data = NSData::with_slice(data); Image(unsafe { - let alloc: id = msg_send![class!(NSImage), alloc]; + let alloc: id = msg_send![Self::class(), alloc]; ShareId::from_ptr(msg_send![alloc, initWithData: data]) }) } diff --git a/src/image/mod.rs b/src/image/mod.rs index ac77893..73a5f48 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -17,11 +17,11 @@ mod appkit; #[cfg(feature = "appkit")] use appkit::register_image_view_class; -//#[cfg(feature = "uikit")] -//mod uikit; +#[cfg(feature = "uikit")] +mod uikit; -//#[cfg(feature = "uikit")] -//use uikit::register_image_view_class; +#[cfg(all(feature = "uikit", not(feature = "appkit")))] +use uikit::register_image_view_class; mod image; pub use image::{DrawConfig, Image, ResizeBehavior}; @@ -194,3 +194,12 @@ impl Drop for ImageView { }*/ } } + +#[test] +fn test_image() { + let image_view = ImageView::new(); + image_view.set_background_color(Color::SystemBlue); + let image_bytes = include_bytes!("../../test-data/favicon.ico"); + let image = Image::with_data(image_bytes); + image_view.set_image(&image); +} diff --git a/src/image/uikit.rs b/src/image/uikit.rs index 1e835ed..57d796f 100644 --- a/src/image/uikit.rs +++ b/src/image/uikit.rs @@ -13,33 +13,15 @@ use crate::utils::load; /// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we /// have separate classes here since we don't want to waste cycles on methods that will never be /// used if there's no delegates. -pub(crate) fn register_view_class() -> *const Class { +pub(crate) fn register_image_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); + let superclass = class!(UIImageView); + let mut decl = ClassDecl::new("RSTImageView", superclass).expect("Failed to get RSTVIEW"); VIEW_CLASS = decl.register(); }); unsafe { VIEW_CLASS } } - -/// Injects an `NSView` subclass, with some callback and pointer ivars for what we -/// need to do. -pub(crate) fn register_view_class_with_delegate() -> *const Class { - static mut VIEW_CLASS: *const Class = 0 as *const Class; - static INIT: Once = Once::new(); - - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap(); - decl.add_ivar::(VIEW_DELEGATE_PTR); - VIEW_CLASS = decl.register(); - }); - - unsafe { - VIEW_CLASS - } -} diff --git a/src/layout/constraint.rs b/src/layout/constraint.rs index 841d684..37b5571 100644 --- a/src/layout/constraint.rs +++ b/src/layout/constraint.rs @@ -101,8 +101,8 @@ impl LayoutConstraint { // // I regret nothing, lol. If you have a better solution I'm all ears. pub fn activate(constraints: &[LayoutConstraint]) { + let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect(); unsafe { - let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect(); let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()]; let _: () = msg_send![class!(NSLayoutConstraint), activateConstraints: constraints]; @@ -110,8 +110,8 @@ impl LayoutConstraint { } pub fn deactivate(constraints: &[LayoutConstraint]) { + let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect(); unsafe { - let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect(); let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()]; let _: () = msg_send![class!(NSLayoutConstraint), deactivateConstraints: constraints]; diff --git a/src/lib.rs b/src/lib.rs index c32e5d8..a85779f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -121,7 +121,7 @@ pub mod color; #[cfg(feature = "appkit")] pub mod control; -#[cfg(feature = "appkit")] +#[cfg(any(feature = "appkit", feature = "uikit"))] pub mod dragdrop; pub mod error; @@ -137,12 +137,14 @@ pub mod filesystem; pub mod foundation; pub mod geometry; -#[cfg(feature = "appkit")] +#[cfg(any(feature = "appkit", feature = "uikit"))] pub mod image; #[cfg(feature = "appkit")] pub mod input; pub(crate) mod invoker; +#[cfg(test)] +mod tests; pub mod keys; @@ -155,7 +157,7 @@ pub mod networking; pub mod notification_center; pub(crate) mod objc_access; -#[cfg(feature = "appkit")] +#[cfg(any(feature = "appkit", feature = "uikit"))] pub mod pasteboard; #[cfg(feature = "appkit")] diff --git a/test-data/favicon.ico b/test-data/favicon.ico new file mode 100644 index 0000000..4b2cfff Binary files /dev/null and b/test-data/favicon.ico differ