From 86980d7329773379f78b8227f4866ad531c18e2a Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Thu, 12 Mar 2020 18:18:32 -0700 Subject: [PATCH] Fixed color math, and ported AutoLayout --- appkit/src/collection_view/traits.rs | 6 ++ appkit/src/color.rs | 85 ++++++++++++++++--------- appkit/src/layout/constraint.rs | 77 +++++++++++++++++++++++ appkit/src/layout/dimension.rs | 70 +++++++++++++++++++++ appkit/src/layout/horizontal.rs | 58 +++++++++++++++++ appkit/src/layout/mod.rs | 23 +++++++ appkit/src/layout/traits.rs | 16 +++++ appkit/src/layout/vertical.rs | 58 +++++++++++++++++ appkit/src/lib.rs | 3 + appkit/src/view/traits.rs | 8 --- appkit/src/view/view.rs | 94 +++++++++++++++++++++++++--- appkit/src/window/config.rs | 2 +- appkit/src/window/handle.rs | 4 +- appkit/src/window/window.rs | 4 +- 14 files changed, 456 insertions(+), 52 deletions(-) create mode 100644 appkit/src/collection_view/traits.rs create mode 100644 appkit/src/layout/constraint.rs create mode 100644 appkit/src/layout/dimension.rs create mode 100644 appkit/src/layout/horizontal.rs create mode 100644 appkit/src/layout/traits.rs create mode 100644 appkit/src/layout/vertical.rs diff --git a/appkit/src/collection_view/traits.rs b/appkit/src/collection_view/traits.rs new file mode 100644 index 0000000..1ce039f --- /dev/null +++ b/appkit/src/collection_view/traits.rs @@ -0,0 +1,6 @@ +//! Traits used for `CollectionView` controllers. More or less maps to the iOS/macOS routines, +//! mapping over the differences between them where appropriate. + +pub trait CollectionViewController { + +} diff --git a/appkit/src/color.rs b/appkit/src/color.rs index 3a09aca..cd1c9b1 100644 --- a/appkit/src/color.rs +++ b/appkit/src/color.rs @@ -30,15 +30,32 @@ impl Color { /// green, blue and alpha channels in that order, and all values will be /// clamped to the 0.0 ... 1.0 range. #[inline] - pub fn new>(red: T, green: T, blue: T, alpha: T) -> Self { - Self::from_u8s( - clamp_unit_f32(red.into()), - clamp_unit_f32(green.into()), - clamp_unit_f32(blue.into()), - clamp_unit_f32(alpha.into()), + pub fn from_floats(red: f32, green: f32, blue: f32, alpha: f32) -> Self { + Self::new( + clamp_unit_f32(red), + clamp_unit_f32(green), + clamp_unit_f32(blue), + clamp_unit_f32(alpha), ) } + /// Returns a transparent color. + #[inline] + pub fn transparent() -> Self { + Self::new(0, 0, 0, 0) + } + + /// Same thing, but with `u8` values instead of floats in the 0 to 1 range. + #[inline] + pub fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Self { + Color { + red: red, + green: green, + blue: blue, + alpha: alpha, + } + } + /// Maps to NS/UIColor. pub fn into_platform_specific_color(&self) -> id { let red = self.red as CGFloat / 255.0; @@ -51,23 +68,6 @@ impl Color { } } - /// Returns a transparent color. - #[inline] - pub fn transparent() -> Self { - Self::new(0., 0., 0., 0.) - } - - /// Same thing, but with `u8` values instead of floats in the 0 to 1 range. - #[inline] - pub fn from_u8s(red: u8, green: u8, blue: u8, alpha: u8) -> Self { - Color { - red: red, - green: green, - blue: blue, - alpha: alpha, - } - } - /// Returns the red channel in a floating point number form, from 0 to 1. #[inline] pub fn red_f32(&self) -> f32 { @@ -91,18 +91,45 @@ impl Color { pub fn alpha_f32(&self) -> f32 { self.alpha as f32 / 255.0 } + + /// Parse a value, per CSS Color Module Level 3. + /// + /// FIXME(#2) Deprecated CSS2 System Colors are not supported yet. + #[cfg(feature="parser")] + pub fn parse_with<'i, 't, ComponentParser>( + component_parser: &ComponentParser, + input: &mut Parser<'i, 't>, + ) -> Result> + where + ComponentParser: ColorComponentParser<'i>, + { + // FIXME: remove clone() when lifetimes are non-lexical + let location = input.current_source_location(); + let token = input.next()?.clone(); + match token { + Token::Hash(ref value) | Token::IDHash(ref value) => { + Color::parse_hash(value.as_bytes()) + } + Token::Ident(ref value) => parse_color_keyword(&*value), + Token::Function(ref name) => { + return input.parse_nested_block(|arguments| { + parse_color_function(component_parser, &*name, arguments) + }) + } + _ => Err(()), + } + .map_err(|()| location.new_unexpected_token_error(token)) + } } -/// A less-verbose way of specifying a generic color, without alpha. #[inline] -pub fn rgb>(red: T, green: T, blue: T) -> Color { - rgba(red.into(), green.into(), blue.into(), 1.) +pub fn rgb(red: u8, green: u8, blue: u8) -> Color { + rgba(red, green, blue, 255) } -/// A less-verbose way of specifying a generic color, with alpha. #[inline] -pub fn rgba>(red: T, green: T, blue: T, alpha: T) -> Color { - Color::new(red.into(), green.into(), blue.into(), alpha.into()) +pub fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Color { + Color::new(red, green, blue, alpha) } fn clamp_unit_f32(val: f32) -> u8 { diff --git a/appkit/src/layout/constraint.rs b/appkit/src/layout/constraint.rs new file mode 100644 index 0000000..35b2473 --- /dev/null +++ b/appkit/src/layout/constraint.rs @@ -0,0 +1,77 @@ +//! A wrapper for `NSLayoutConstraint` that's more general in nature. You can think of this as an +//! escape hatch, if you need it (we use it for things like width and height, which aren't handled +//! by an axis). + +use cocoa::base::id; +use core_graphics::base::CGFloat; + +use objc::{class, msg_send, sel, sel_impl}; +use objc::runtime::Object; +use objc_id::ShareId; + +/// A wrapper for `NSLayoutConstraint`. This both acts as a central path through which to activate +/// constraints, as well as a wrapper for layout constraints that are not axis bound (e.g, width or +/// height). +#[derive(Clone, Debug)] +pub struct LayoutConstraint { + /// A shared pointer to the underlying view. Provided your view isn't dropped, this will always + /// be valid. + pub constraint: ShareId, + + /// The offset used in computing this constraint. + pub offset: f64, + + /// The multiplier used in computing this constraint. + pub multiplier: f64, + + /// The priority used in computing this constraint. + pub priority: f64, +} + +impl LayoutConstraint { + /// An internal method for wrapping existing constraints. + pub(crate) fn new(object: id) -> Self { + LayoutConstraint { + constraint: unsafe { ShareId::from_ptr(object) }, + offset: 0.0, + multiplier: 0.0, + priority: 0.0 + } + } + + /// Sets the offset for this constraint. + pub fn offset>(self, offset: F) -> Self { + let offset: f64 = offset.into(); + + unsafe { + let o = offset as CGFloat; + let _: () = msg_send![&*self.constraint, setConstant:o]; + } + + LayoutConstraint { + constraint: self.constraint, + offset: offset, + multiplier: self.multiplier, + priority: self.priority + } + } + + /// Call this with your batch of constraints to activate them. + // If you're astute, you'll note that, yes... this is kind of hacking around some + // borrowing rules with how objc_id::Id/objc_id::ShareId works. In this case, to + // support the way autolayout constraints work over in the cocoa runtime, we need to be + // able to clone these and pass them around... while also getting certain references to + // them. + // + // I regret nothing, lol. If you have a better solution I'm all ears. + pub fn activate(constraints: &[LayoutConstraint]) { + 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]; + } + } +} diff --git a/appkit/src/layout/dimension.rs b/appkit/src/layout/dimension.rs new file mode 100644 index 0000000..d20a1d7 --- /dev/null +++ b/appkit/src/layout/dimension.rs @@ -0,0 +1,70 @@ +//! A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height` +//! values for how a given view should layout. + +use cocoa::base::id; +use core_graphics::base::CGFloat; + +use objc::{msg_send, sel, sel_impl}; +use objc::runtime::Object; +use objc_id::ShareId; + +use crate::layout::constraint::LayoutConstraint; + +/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a +/// factory/helper for creating `LayoutConstraint` objects based on your views. +#[derive(Clone, Debug, Default)] +pub struct LayoutAnchorDimension(pub Option>); + +impl LayoutAnchorDimension { + /// An internal method for wrapping existing anchors. + pub(crate) fn new(object: id) -> Self { + LayoutAnchorDimension(Some(unsafe { + ShareId::from_ptr(object) + })) + } + + /// Return a constraint equal to a constant value. + pub fn constraint_equal_to_constant(&self, constant: f64) -> LayoutConstraint { + match &self.0 { + Some(from) => LayoutConstraint::new(unsafe { + let value = constant as CGFloat; + msg_send![*from, constraintEqualToConstant:value] + }), + + _ => { panic!("Attempted to create constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint equal to another dimension anchor. + pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint greater than or equal to another dimension anchor. + pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintGreaterThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint less than or equal to another dimension anchor. + pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintLessThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create constraints with an uninitialized anchor!"); } + } + } +} diff --git a/appkit/src/layout/horizontal.rs b/appkit/src/layout/horizontal.rs new file mode 100644 index 0000000..73fc5ab --- /dev/null +++ b/appkit/src/layout/horizontal.rs @@ -0,0 +1,58 @@ +//! A wrapper for `NSLayoutAnchorX`, which is typically used to handle values for how a +//! given view should layout along the x-axis. Of note: the only thing that can't be protected +//! against is mixing/matching incorrect left/leading and right/trailing anchors. Be careful! + +use cocoa::base::id; + +use objc::{msg_send, sel, sel_impl}; +use objc::runtime::Object; +use objc_id::ShareId; + +use crate::layout::constraint::LayoutConstraint; + +/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a +/// factory/helper for creating `LayoutConstraint` objects based on your views. +#[derive(Clone, Debug, Default)] +pub struct LayoutAnchorX(pub Option>); + +impl LayoutAnchorX { + /// An internal method for wrapping existing anchors. + pub(crate) fn new(object: id) -> Self { + LayoutAnchorX(Some(unsafe { + ShareId::from_ptr(object) + })) + } + + /// Return a constraint equal to another horizontal anchor. + pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create horizontal constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint greater than or equal to another horizontal anchor. + pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintGreaterThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create horizontal constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint less than or equal to another horizontal anchor. + pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintLessThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create horizontal constraints with an uninitialized anchor!"); } + } + } +} diff --git a/appkit/src/layout/mod.rs b/appkit/src/layout/mod.rs index e69de29..f481aaf 100644 --- a/appkit/src/layout/mod.rs +++ b/appkit/src/layout/mod.rs @@ -0,0 +1,23 @@ +//! A wrapper for `NSLayoutConstraint`, enabling AutoLayout across views. This does a few things +//! that might seem weird, but are generally good and rely on the idea that this is all written +//! once and used often. +//! +//! Notably: there are 3 structs for wrapping layout constraints; in practice, you likely don't need to +//! care. This is because we want to detect at compile time invalid layout items - i.e, you should +//! not be able to attach a left-axis to a top-axis. In Rust this is a bit tricky, but by using +//! some `impl Trait`'s in the right places we can mostly hide this detail away. + +pub mod traits; +pub use traits::Layout; + +pub mod constraint; +pub use constraint::LayoutConstraint; + +pub mod dimension; +pub use dimension::LayoutAnchorDimension; + +pub mod horizontal; +pub use horizontal::LayoutAnchorX; + +pub mod vertical; +pub use vertical::LayoutAnchorY; diff --git a/appkit/src/layout/traits.rs b/appkit/src/layout/traits.rs new file mode 100644 index 0000000..0977433 --- /dev/null +++ b/appkit/src/layout/traits.rs @@ -0,0 +1,16 @@ +//! Various traits related to controllers opting in to autolayout routines and support for view +//! heirarchies. + +use objc::runtime::Object; +use objc_id::ShareId; + +/// A trait that view wrappers must conform to. Enables managing the subview tree. +pub trait Layout { + /// Returns a reference to the backing Objective-C layer. This is optional, as we try to keep + /// the general lazy-loading approach Cocoa has. This may change in the future, and in general + /// this shouldn't affect your code too much (if at all). + fn get_backing_node(&self) -> Option>; + + /// This trait should implement adding a view to the subview tree for a given view. + fn add_subview(&self, _view: &V); +} diff --git a/appkit/src/layout/vertical.rs b/appkit/src/layout/vertical.rs new file mode 100644 index 0000000..fa7620b --- /dev/null +++ b/appkit/src/layout/vertical.rs @@ -0,0 +1,58 @@ +//! A wrapper for `NSLayoutAnchorX`, which is typically used to handle values for how a +//! given view should layout along the x-axis. Of note: the only thing that can't be protected +//! against is mixing/matching incorrect left/leading and right/trailing anchors. Be careful! + +use cocoa::base::id; + +use objc::{msg_send, sel, sel_impl}; +use objc::runtime::Object; +use objc_id::ShareId; + +use crate::layout::constraint::LayoutConstraint; + +/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a +/// factory/helper for creating `LayoutConstraint` objects based on your views. +#[derive(Clone, Debug, Default)] +pub struct LayoutAnchorY(pub Option>); + +impl LayoutAnchorY { + /// An internal method for wrapping existing constraints. + pub(crate) fn new(object: id) -> Self { + LayoutAnchorY(Some(unsafe { + ShareId::from_ptr(object) + })) + } + + /// Return a constraint equal to another vertical anchor. + pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create vertical constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint greater than or equal to another vertical anchor. + pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintGreaterThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create vertical constraints with an uninitialized anchor!"); } + } + } + + /// Return a constraint less than or equal to another vertical anchor. + pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint { + match (&self.0, &anchor_to.0) { + (Some(from), Some(to)) => LayoutConstraint::new(unsafe { + msg_send![*from, constraintLessThanOrEqualToAnchor:&*to] + }), + + _ => { panic!("Attempted to create vertical constraints with an uninitialized anchor!"); } + } + } +} diff --git a/appkit/src/lib.rs b/appkit/src/lib.rs index b843aa5..b6982bf 100644 --- a/appkit/src/lib.rs +++ b/appkit/src/lib.rs @@ -31,6 +31,7 @@ pub mod error; pub mod events; pub mod filesystem; pub mod geometry; +pub mod layout; pub mod menu; pub mod networking; pub mod notifications; @@ -47,6 +48,8 @@ pub use url; pub mod prelude { pub use crate::app::{App, AppDelegate, Dispatcher}; + pub use crate::layout::LayoutConstraint; + pub use crate::menu::{Menu, MenuItem}; pub use crate::notifications::{Notification, NotificationCenter, NotificationAuthOption}; pub use crate::toolbar::{Toolbar, ToolbarController, ToolbarHandle}; diff --git a/appkit/src/view/traits.rs b/appkit/src/view/traits.rs index 408b426..8ba7b67 100644 --- a/appkit/src/view/traits.rs +++ b/appkit/src/view/traits.rs @@ -1,16 +1,8 @@ //! Various traits used for Views. -use objc::runtime::Object; - -use objc_id::ShareId; - use crate::dragdrop::{DragInfo, DragOperation}; use crate::view::ViewHandle; -pub trait Node { - fn get_backing_node(&self) -> Option>; -} - pub trait ViewController { /// Where possible, we try to respect the lazy-ish-loading of macOS/iOS systems. This hook /// notifies you when the `View` has actually loaded into memory, and you're free to do things diff --git a/appkit/src/view/view.rs b/appkit/src/view/view.rs index f6c0b75..ab0e432 100644 --- a/appkit/src/view/view.rs +++ b/appkit/src/view/view.rs @@ -12,22 +12,68 @@ use objc::{msg_send, sel, sel_impl}; use crate::color::Color; use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR}; +use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::pasteboard::PasteboardType; -use crate::view::traits::{Node, ViewController}; use crate::view::controller::register_controller_class; +use crate::view::traits::ViewController; /// A clone-able handler to a `ViewController` reference in the Objective C runtime. We use this /// instead of a stock `View` for easier recordkeeping, since it'll need to hold the `View` on that /// side anyway. #[derive(Debug, Default, Clone)] -pub struct ViewHandle(Option>); +pub struct ViewHandle { + /// A pointer to the Objective-C runtime view controller. + pub objc: Option>, + + /// A pointer to the Objective-C runtime top layout constraint. + pub top: LayoutAnchorY, + + /// A pointer to the Objective-C runtime leading layout constraint. + pub leading: LayoutAnchorX, + + /// A pointer to the Objective-C runtime trailing layout constraint. + pub trailing: LayoutAnchorX, + + /// A pointer to the Objective-C runtime bottom layout constraint. + pub bottom: LayoutAnchorY, + + /// A pointer to the Objective-C runtime width layout constraint. + pub width: LayoutAnchorDimension, + + /// A pointer to the Objective-C runtime height layout constraint. + pub height: LayoutAnchorDimension, + + /// A pointer to the Objective-C runtime center X layout constraint. + pub center_x: LayoutAnchorX, + + /// A pointer to the Objective-C runtime center Y layout constraint. + pub center_y: LayoutAnchorY +} impl ViewHandle { + pub(crate) fn new(object: ShareId) -> Self { + let view: id = unsafe { + msg_send![&*object, view] + }; + + ViewHandle { + objc: Some(object), + top: LayoutAnchorY::new(unsafe { msg_send![view, topAnchor] }), + leading: LayoutAnchorX::new(unsafe { msg_send![view, leadingAnchor] }), + trailing: LayoutAnchorX::new(unsafe { msg_send![view, trailingAnchor] }), + bottom: LayoutAnchorY::new(unsafe { msg_send![view, bottomAnchor] }), + width: LayoutAnchorDimension::new(unsafe { msg_send![view, widthAnchor] }), + height: LayoutAnchorDimension::new(unsafe { msg_send![view, heightAnchor] }), + center_x: LayoutAnchorX::new(unsafe { msg_send![view, centerXAnchor] }), + center_y: LayoutAnchorY::new(unsafe { msg_send![view, centerYAnchor] }), + } + } + /// Call this to set the background color for the backing layer. pub fn set_background_color(&self, color: Color) { - if let Some(controller) = &self.0 { + if let Some(objc) = &self.objc { unsafe { - let view: id = msg_send![*controller, view]; + let view: id = msg_send![*objc, view]; (*view).set_ivar(BACKGROUND_COLOR, color.into_platform_specific_color()); let _: () = msg_send![view, setNeedsDisplay:YES]; } @@ -36,17 +82,31 @@ impl ViewHandle { /// Register this view for drag and drop operations. pub fn register_for_dragged_types(&self, types: &[PasteboardType]) { - if let Some(controller) = &self.0 { + if let Some(objc) = &self.objc { unsafe { let types = NSArray::arrayWithObjects(nil, &types.iter().map(|t| { t.to_nsstring() }).collect::>()); - let view: id = msg_send![*controller, view]; + let view: id = msg_send![*objc, view]; let _: () = msg_send![view, registerForDraggedTypes:types]; } } } + + pub fn add_subview(&self, subview: &T) { + if let Some(this) = &self.objc { + if let Some(subview_controller) = subview.get_backing_node() { + unsafe { + let _: () = msg_send![*this, addChildViewController:&*subview_controller]; + + let subview: id = msg_send![&*subview_controller, view]; + let view: id = msg_send![*this, view]; + let _: () = msg_send![view, addSubview:subview]; + } + } + } + } } /// A `View` wraps two different controllers - one on the Objective-C/Cocoa side, which forwards @@ -80,14 +140,16 @@ impl View where T: ViewController + 'static { ShareId::from_ptr(view_controller) }; + let handle = ViewHandle::new(inner); + { let mut vc = controller.borrow_mut(); - (*vc).did_load(ViewHandle(Some(inner.clone()))); + (*vc).did_load(handle.clone()); } View { internal_callback_ptr: internal_callback_ptr, - objc_controller: ViewHandle(Some(inner)), + objc_controller: handle, controller: controller } } @@ -99,12 +161,24 @@ impl View where T: ViewController + 'static { pub fn register_for_dragged_types(&self, types: &[PasteboardType]) { self.objc_controller.register_for_dragged_types(types); } + + pub fn width(&self) -> &LayoutAnchorDimension { + &self.objc_controller.width + } + + pub fn height(&self) -> &LayoutAnchorDimension { + &self.objc_controller.height + } } -impl Node for View { +impl Layout for View { /// Returns the Objective-C object used for handling the view heirarchy. fn get_backing_node(&self) -> Option> { - self.objc_controller.0.clone() + self.objc_controller.objc.clone() + } + + fn add_subview(&self, subview: &V) { + self.objc_controller.add_subview(subview); } } diff --git a/appkit/src/window/config.rs b/appkit/src/window/config.rs index 3e114ce..15d2808 100644 --- a/appkit/src/window/config.rs +++ b/appkit/src/window/config.rs @@ -35,7 +35,7 @@ impl Default for WindowConfig { let dimensions = NSRect::new(NSPoint::new(0., 0.), NSSize::new(800., 600.)); let style = WindowStyle::Resizable | WindowStyle::Miniaturizable | WindowStyle::UnifiedTitleAndToolbar | - WindowStyle::Closable | WindowStyle::Titled | WindowStyle::FullSizeContentView; + WindowStyle::Closable | WindowStyle::Titled; let alloc: id = msg_send![class!(NSWindow), alloc]; let window: id = msg_send![alloc, initWithContentRect:dimensions styleMask:style backing:2 as NSUInteger defer:YES]; diff --git a/appkit/src/window/handle.rs b/appkit/src/window/handle.rs index 31b6615..e69f6d6 100644 --- a/appkit/src/window/handle.rs +++ b/appkit/src/window/handle.rs @@ -11,7 +11,7 @@ use objc::{msg_send, sel, sel_impl}; use objc::runtime::Object; use objc_id::ShareId; -use crate::view::traits::Node; +use crate::layout::traits::Layout; use crate::toolbar::{Toolbar, ToolbarController}; @@ -100,7 +100,7 @@ impl WindowHandle { } /// Used for setting the content view controller for this window. - pub fn set_content_view_controller(&self, view_controller: &T) { + pub fn set_content_view_controller(&self, view_controller: &T) { if let Some(controller) = &self.0 { unsafe { if let Some(vc) = view_controller.get_backing_node() { diff --git a/appkit/src/window/window.rs b/appkit/src/window/window.rs index 236e4da..9e16329 100644 --- a/appkit/src/window/window.rs +++ b/appkit/src/window/window.rs @@ -10,8 +10,8 @@ use objc::{msg_send, sel, sel_impl}; use objc_id::ShareId; use crate::constants::WINDOW_CONTROLLER_PTR; +use crate::layout::traits::Layout; use crate::toolbar::{Toolbar, ToolbarController}; -use crate::view::traits::Node; use crate::window::handle::WindowHandle; use crate::window::traits::WindowController; use crate::window::controller::register_window_controller_class; @@ -98,7 +98,7 @@ impl Window where T: WindowController + 'static { } /// Sets the content view controller for the window. - pub fn set_content_view_controller(&self, view_controller: &VC) { + pub fn set_content_view_controller(&self, view_controller: &VC) { self.objc_controller.set_content_view_controller(view_controller); }