Fixed color math, and ported AutoLayout

This commit is contained in:
Ryan McGrath 2020-03-12 18:18:32 -07:00
parent 3d93b04455
commit 86980d7329
No known key found for this signature in database
GPG key ID: 811674B62B666830
14 changed files with 456 additions and 52 deletions

View file

@ -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 {
}

View file

@ -30,15 +30,32 @@ impl Color {
/// green, blue and alpha channels in that order, and all values will be /// green, blue and alpha channels in that order, and all values will be
/// clamped to the 0.0 ... 1.0 range. /// clamped to the 0.0 ... 1.0 range.
#[inline] #[inline]
pub fn new<T: Into<f32>>(red: T, green: T, blue: T, alpha: T) -> Self { pub fn from_floats(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
Self::from_u8s( Self::new(
clamp_unit_f32(red.into()), clamp_unit_f32(red),
clamp_unit_f32(green.into()), clamp_unit_f32(green),
clamp_unit_f32(blue.into()), clamp_unit_f32(blue),
clamp_unit_f32(alpha.into()), 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. /// Maps to NS/UIColor.
pub fn into_platform_specific_color(&self) -> id { pub fn into_platform_specific_color(&self) -> id {
let red = self.red as CGFloat / 255.0; 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. /// Returns the red channel in a floating point number form, from 0 to 1.
#[inline] #[inline]
pub fn red_f32(&self) -> f32 { pub fn red_f32(&self) -> f32 {
@ -91,18 +91,45 @@ impl Color {
pub fn alpha_f32(&self) -> f32 { pub fn alpha_f32(&self) -> f32 {
self.alpha as f32 / 255.0 self.alpha as f32 / 255.0
} }
/// Parse a <color> 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<Color, ParseError<'i, ComponentParser::Error>>
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] #[inline]
pub fn rgb<T: Into<f32>>(red: T, green: T, blue: T) -> Color { pub fn rgb(red: u8, green: u8, blue: u8) -> Color {
rgba(red.into(), green.into(), blue.into(), 1.) rgba(red, green, blue, 255)
} }
/// A less-verbose way of specifying a generic color, with alpha.
#[inline] #[inline]
pub fn rgba<T: Into<f32>>(red: T, green: T, blue: T, alpha: T) -> Color { pub fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Color {
Color::new(red.into(), green.into(), blue.into(), alpha.into()) Color::new(red, green, blue, alpha)
} }
fn clamp_unit_f32(val: f32) -> u8 { fn clamp_unit_f32(val: f32) -> u8 {

View file

@ -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<Object>,
/// 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<F: Into<f64>>(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];
}
}
}

View file

@ -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<ShareId<Object>>);
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!"); }
}
}
}

View file

@ -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<ShareId<Object>>);
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!"); }
}
}
}

View file

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

View file

@ -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<ShareId<Object>>;
/// This trait should implement adding a view to the subview tree for a given view.
fn add_subview<V: Layout>(&self, _view: &V);
}

View file

@ -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<ShareId<Object>>);
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!"); }
}
}
}

View file

@ -31,6 +31,7 @@ pub mod error;
pub mod events; pub mod events;
pub mod filesystem; pub mod filesystem;
pub mod geometry; pub mod geometry;
pub mod layout;
pub mod menu; pub mod menu;
pub mod networking; pub mod networking;
pub mod notifications; pub mod notifications;
@ -47,6 +48,8 @@ pub use url;
pub mod prelude { pub mod prelude {
pub use crate::app::{App, AppDelegate, Dispatcher}; pub use crate::app::{App, AppDelegate, Dispatcher};
pub use crate::layout::LayoutConstraint;
pub use crate::menu::{Menu, MenuItem}; pub use crate::menu::{Menu, MenuItem};
pub use crate::notifications::{Notification, NotificationCenter, NotificationAuthOption}; pub use crate::notifications::{Notification, NotificationCenter, NotificationAuthOption};
pub use crate::toolbar::{Toolbar, ToolbarController, ToolbarHandle}; pub use crate::toolbar::{Toolbar, ToolbarController, ToolbarHandle};

View file

@ -1,16 +1,8 @@
//! Various traits used for Views. //! Various traits used for Views.
use objc::runtime::Object;
use objc_id::ShareId;
use crate::dragdrop::{DragInfo, DragOperation}; use crate::dragdrop::{DragInfo, DragOperation};
use crate::view::ViewHandle; use crate::view::ViewHandle;
pub trait Node {
fn get_backing_node(&self) -> Option<ShareId<Object>>;
}
pub trait ViewController { pub trait ViewController {
/// Where possible, we try to respect the lazy-ish-loading of macOS/iOS systems. This hook /// 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 /// notifies you when the `View` has actually loaded into memory, and you're free to do things

View file

@ -12,22 +12,68 @@ use objc::{msg_send, sel, sel_impl};
use crate::color::Color; use crate::color::Color;
use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR}; use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR};
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
use crate::pasteboard::PasteboardType; use crate::pasteboard::PasteboardType;
use crate::view::traits::{Node, ViewController};
use crate::view::controller::register_controller_class; 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 /// 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 /// instead of a stock `View` for easier recordkeeping, since it'll need to hold the `View` on that
/// side anyway. /// side anyway.
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct ViewHandle(Option<ShareId<Object>>); pub struct ViewHandle {
/// A pointer to the Objective-C runtime view controller.
pub objc: Option<ShareId<Object>>,
/// 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 { impl ViewHandle {
pub(crate) fn new(object: ShareId<Object>) -> 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. /// Call this to set the background color for the backing layer.
pub fn set_background_color(&self, color: Color) { pub fn set_background_color(&self, color: Color) {
if let Some(controller) = &self.0 { if let Some(objc) = &self.objc {
unsafe { 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()); (*view).set_ivar(BACKGROUND_COLOR, color.into_platform_specific_color());
let _: () = msg_send![view, setNeedsDisplay:YES]; let _: () = msg_send![view, setNeedsDisplay:YES];
} }
@ -36,17 +82,31 @@ impl ViewHandle {
/// Register this view for drag and drop operations. /// Register this view for drag and drop operations.
pub fn register_for_dragged_types(&self, types: &[PasteboardType]) { pub fn register_for_dragged_types(&self, types: &[PasteboardType]) {
if let Some(controller) = &self.0 { if let Some(objc) = &self.objc {
unsafe { unsafe {
let types = NSArray::arrayWithObjects(nil, &types.iter().map(|t| { let types = NSArray::arrayWithObjects(nil, &types.iter().map(|t| {
t.to_nsstring() t.to_nsstring()
}).collect::<Vec<id>>()); }).collect::<Vec<id>>());
let view: id = msg_send![*controller, view]; let view: id = msg_send![*objc, view];
let _: () = msg_send![view, registerForDraggedTypes:types]; let _: () = msg_send![view, registerForDraggedTypes:types];
} }
} }
} }
pub fn add_subview<T: Layout>(&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 /// A `View` wraps two different controllers - one on the Objective-C/Cocoa side, which forwards
@ -80,14 +140,16 @@ impl<T> View<T> where T: ViewController + 'static {
ShareId::from_ptr(view_controller) ShareId::from_ptr(view_controller)
}; };
let handle = ViewHandle::new(inner);
{ {
let mut vc = controller.borrow_mut(); let mut vc = controller.borrow_mut();
(*vc).did_load(ViewHandle(Some(inner.clone()))); (*vc).did_load(handle.clone());
} }
View { View {
internal_callback_ptr: internal_callback_ptr, internal_callback_ptr: internal_callback_ptr,
objc_controller: ViewHandle(Some(inner)), objc_controller: handle,
controller: controller controller: controller
} }
} }
@ -99,12 +161,24 @@ impl<T> View<T> where T: ViewController + 'static {
pub fn register_for_dragged_types(&self, types: &[PasteboardType]) { pub fn register_for_dragged_types(&self, types: &[PasteboardType]) {
self.objc_controller.register_for_dragged_types(types); self.objc_controller.register_for_dragged_types(types);
} }
pub fn width(&self) -> &LayoutAnchorDimension {
&self.objc_controller.width
} }
impl<T> Node for View<T> { pub fn height(&self) -> &LayoutAnchorDimension {
&self.objc_controller.height
}
}
impl<T> Layout for View<T> {
/// Returns the Objective-C object used for handling the view heirarchy. /// Returns the Objective-C object used for handling the view heirarchy.
fn get_backing_node(&self) -> Option<ShareId<Object>> { fn get_backing_node(&self) -> Option<ShareId<Object>> {
self.objc_controller.0.clone() self.objc_controller.objc.clone()
}
fn add_subview<V: Layout>(&self, subview: &V) {
self.objc_controller.add_subview(subview);
} }
} }

View file

@ -35,7 +35,7 @@ impl Default for WindowConfig {
let dimensions = NSRect::new(NSPoint::new(0., 0.), NSSize::new(800., 600.)); let dimensions = NSRect::new(NSPoint::new(0., 0.), NSSize::new(800., 600.));
let style = WindowStyle::Resizable | WindowStyle::Miniaturizable | WindowStyle::UnifiedTitleAndToolbar | 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 alloc: id = msg_send![class!(NSWindow), alloc];
let window: id = msg_send![alloc, initWithContentRect:dimensions styleMask:style backing:2 as NSUInteger defer:YES]; let window: id = msg_send![alloc, initWithContentRect:dimensions styleMask:style backing:2 as NSUInteger defer:YES];

View file

@ -11,7 +11,7 @@ use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId; use objc_id::ShareId;
use crate::view::traits::Node; use crate::layout::traits::Layout;
use crate::toolbar::{Toolbar, ToolbarController}; use crate::toolbar::{Toolbar, ToolbarController};
@ -100,7 +100,7 @@ impl WindowHandle {
} }
/// Used for setting the content view controller for this window. /// Used for setting the content view controller for this window.
pub fn set_content_view_controller<T: Node + 'static>(&self, view_controller: &T) { pub fn set_content_view_controller<T: Layout + 'static>(&self, view_controller: &T) {
if let Some(controller) = &self.0 { if let Some(controller) = &self.0 {
unsafe { unsafe {
if let Some(vc) = view_controller.get_backing_node() { if let Some(vc) = view_controller.get_backing_node() {

View file

@ -10,8 +10,8 @@ use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::constants::WINDOW_CONTROLLER_PTR; use crate::constants::WINDOW_CONTROLLER_PTR;
use crate::layout::traits::Layout;
use crate::toolbar::{Toolbar, ToolbarController}; use crate::toolbar::{Toolbar, ToolbarController};
use crate::view::traits::Node;
use crate::window::handle::WindowHandle; use crate::window::handle::WindowHandle;
use crate::window::traits::WindowController; use crate::window::traits::WindowController;
use crate::window::controller::register_window_controller_class; use crate::window::controller::register_window_controller_class;
@ -98,7 +98,7 @@ impl<T> Window<T> where T: WindowController + 'static {
} }
/// Sets the content view controller for the window. /// Sets the content view controller for the window.
pub fn set_content_view_controller<VC: Node + 'static>(&self, view_controller: &VC) { pub fn set_content_view_controller<VC: Layout + 'static>(&self, view_controller: &VC) {
self.objc_controller.set_content_view_controller(view_controller); self.objc_controller.set_content_view_controller(view_controller);
} }