From c1da7b1b3727cc3670b3a1b152f795d7a194b960 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Fri, 20 Mar 2020 15:03:19 -0700 Subject: [PATCH] Clean up warnings, finish moving View/ViewController to new paradigm, general cleanup - need to rewrite docs --- appkit/app/class.rs | 1 - appkit/app/delegate.rs | 4 +-- appkit/app/mod.rs | 3 +- appkit/constants.rs | 3 -- appkit/utils.rs | 7 +++++ appkit/view/class.rs | 26 ++------------- appkit/view/controller/class.rs | 3 +- appkit/view/controller/mod.rs | 32 +++++++++++-------- appkit/view/mod.rs | 56 +++++++++++++++------------------ appkit/window/controller/mod.rs | 12 ++++--- appkit/window/mod.rs | 19 +++++------ 11 files changed, 77 insertions(+), 89 deletions(-) diff --git a/appkit/app/class.rs b/appkit/app/class.rs index 1e642b2..fe60ef1 100644 --- a/appkit/app/class.rs +++ b/appkit/app/class.rs @@ -5,7 +5,6 @@ use std::sync::Once; use objc::class; -//, msg_send, sel, sel_impl}; use objc::declare::ClassDecl; use objc::runtime::{Class}; diff --git a/appkit/app/delegate.rs b/appkit/app/delegate.rs index e54170b..511626f 100644 --- a/appkit/app/delegate.rs +++ b/appkit/app/delegate.rs @@ -14,10 +14,10 @@ use objc::runtime::{Class, Object, Sel}; use url::Url; -use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString}; +use crate::app::APP_PTR; use crate::app::traits::AppDelegate; -use crate::constants::APP_PTR; use crate::error::AppKitError; +use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString}; use crate::printing::PrintSettings; use crate::user_activity::UserActivity; diff --git a/appkit/app/mod.rs b/appkit/app/mod.rs index 8b824cc..1222f2b 100644 --- a/appkit/app/mod.rs +++ b/appkit/app/mod.rs @@ -6,7 +6,6 @@ use objc::runtime::Object; use objc::{class, msg_send, sel, sel_impl}; use crate::foundation::{id, YES, NO, NSUInteger, AutoReleasePool}; -use crate::constants::APP_PTR; use crate::menu::Menu; mod class; @@ -21,6 +20,8 @@ pub use enums::AppDelegateResponse; pub mod traits; pub use traits::{AppDelegate, Dispatcher}; +pub(crate) static APP_PTR: &str = "rstAppPtr"; + /// A handler to make some boilerplate less annoying. #[inline] fn shared_application(handler: F) { diff --git a/appkit/constants.rs b/appkit/constants.rs index 0ac76cc..0c17a1e 100644 --- a/appkit/constants.rs +++ b/appkit/constants.rs @@ -1,10 +1,7 @@ //! Constants typically used for referencing around in the Objective-C runtime. //! Specific to this crate. -pub(crate) static APP_PTR: &str = "rstAppPtr"; -pub(crate) static BACKGROUND_COLOR: &str = "rstBackgroundColor"; pub(crate) static TOOLBAR_PTR: &str = "rstToolbarPtr"; -pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr"; #[cfg(feature = "webview")] pub(crate) static WEBVIEW_CONFIG_VAR: &str = "rstWebViewConfig"; diff --git a/appkit/utils.rs b/appkit/utils.rs index 59bfcb9..3d38678 100644 --- a/appkit/utils.rs +++ b/appkit/utils.rs @@ -6,6 +6,13 @@ use std::rc::Rc; use std::cell::RefCell; use objc::runtime::Object; +use objc_id::ShareId; + +/// A generic trait that's used throughout multiple different controls in this framework - acts as +/// a guard for whether something is a (View|etc)Controller. Only needs to return the backing node. +pub trait Controller { + fn get_backing_node(&self) -> ShareId; +} /// Used for moving a pointer back into an Rc, so we can work with the object held behind it. Note /// that it's very important to make sure you reverse this when you're done (using diff --git a/appkit/view/class.rs b/appkit/view/class.rs index 3e2dc69..ca7caee 100644 --- a/appkit/view/class.rs +++ b/appkit/view/class.rs @@ -12,13 +12,12 @@ use std::sync::Once; use objc::declare::ClassDecl; use objc::runtime::{Class, Object, Sel, BOOL}; -use objc::{class, msg_send, sel, sel_impl}; +use objc::{class, sel, sel_impl}; use objc_id::Id; -use crate::foundation::{id, nil, YES, NO, NSUInteger}; -use crate::constants::{BACKGROUND_COLOR, VIEW_DELEGATE_PTR}; +use crate::foundation::{id, YES, NO, NSUInteger}; use crate::dragdrop::DragInfo; -use crate::view::traits::ViewDelegate; +use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; use crate::utils::load; /// Enforces normalcy, or: a needlessly cruel method in terms of the name. You get the idea though. @@ -26,19 +25,6 @@ extern fn enforce_normalcy(_: &Object, _: Sel) -> BOOL { return YES; } -/// Used for handling background colors in layer backed views (which is the default here). -/// @TODO: This could be more efficient, I think. -extern fn update_layer(this: &Object, _: Sel) { - unsafe { - let background_color: id = *this.get_ivar(BACKGROUND_COLOR); - if background_color != nil { - let layer: id = msg_send![this, layer]; - let cg: id = msg_send![background_color, CGColor]; - let _: () = msg_send![layer, setBackgroundColor:cg]; - } - } -} - /// Called when a drag/drop operation has entered this view. extern fn dragging_entered(this: &mut Object, _: Sel, info: id) -> NSUInteger { let view = load::(this, VIEW_DELEGATE_PTR); @@ -132,10 +118,7 @@ pub(crate) fn register_view_class() -> *const Class { let superclass = class!(NSView); let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); - decl.add_ivar::(BACKGROUND_COLOR); decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); - //decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern fn(&Object, _) -> BOOL); - //decl.add_method(sel!(updateLayer), update_layer as extern fn(&Object, _)); VIEW_CLASS = decl.register(); }); @@ -156,11 +139,8 @@ pub(crate) fn register_view_class_with_delegate() -> *const Cla // A pointer to the "view controller" on the Rust side. It's expected that this doesn't // move. decl.add_ivar::(VIEW_DELEGATE_PTR); - decl.add_ivar::(BACKGROUND_COLOR); decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); - decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern fn(&Object, _) -> BOOL); - decl.add_method(sel!(updateLayer), update_layer as extern fn(&Object, _)); // Drag and drop operations (e.g, accepting files) decl.add_method(sel!(draggingEntered:), dragging_entered:: as extern fn (&mut Object, _, _) -> NSUInteger); diff --git a/appkit/view/controller/class.rs b/appkit/view/controller/class.rs index 4f7fad1..a8a7b7f 100644 --- a/appkit/view/controller/class.rs +++ b/appkit/view/controller/class.rs @@ -7,8 +7,7 @@ use objc::declare::ClassDecl; use objc::runtime::{Class, Object, Sel}; use objc::{class, sel, sel_impl}; -use crate::constants::VIEW_DELEGATE_PTR; -use crate::view::traits::ViewDelegate; +use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; use crate::utils::load; /// Called when the view controller receives a `viewWillAppear` message. diff --git a/appkit/view/controller/mod.rs b/appkit/view/controller/mod.rs index 81b23d3..c2cf1c5 100644 --- a/appkit/view/controller/mod.rs +++ b/appkit/view/controller/mod.rs @@ -1,36 +1,42 @@ -use std::rc::Rc; -use std::cell::RefCell; - use objc_id::ShareId; use objc::runtime::Object; use objc::{msg_send, sel, sel_impl}; -use crate::foundation::{id, NO}; -use crate::constants::VIEW_DELEGATE_PTR; +use crate::foundation::id; use crate::layout::{Layout}; -use crate::view::traits::ViewDelegate; +use crate::view::{VIEW_DELEGATE_PTR, View, ViewDelegate}; mod class; use class::register_view_controller_class; //#[derive(Debug)] -pub struct ViewController { +pub struct ViewController { pub objc: ShareId, - pub view: Box + pub view: View } -impl ViewController { - pub fn new(view: T) -> Self { - let view = Box::new(view); +impl ViewController where T: ViewDelegate + 'static { + pub fn new(delegate: T) -> Self { + let mut view = View::with(delegate); let objc = unsafe { let vc: id = msg_send![register_view_controller_class::(), new]; + + if let Some(ptr)= view.internal_callback_ptr { + (&mut *vc).set_ivar(VIEW_DELEGATE_PTR, ptr as usize); + } + let _: () = msg_send![vc, setView:&*view.get_backing_node()]; - let ptr: *const T = &*view; - (&mut *vc).set_ivar(VIEW_DELEGATE_PTR, ptr as usize); + ShareId::from_ptr(vc) }; + let handle = view.clone_as_handle(); + if let Some(view_delegate) = &mut view.delegate { + let mut view_delegate = view_delegate.borrow_mut(); + (*view_delegate).did_load(handle); + } + ViewController { objc: objc, view: view diff --git a/appkit/view/mod.rs b/appkit/view/mod.rs index ad6c1c9..1d71085 100644 --- a/appkit/view/mod.rs +++ b/appkit/view/mod.rs @@ -14,7 +14,6 @@ use objc::{msg_send, sel, sel_impl}; use crate::foundation::{id, YES, NO, NSArray, NSString}; use crate::color::Color; -use crate::constants::{BACKGROUND_COLOR, VIEW_DELEGATE_PTR}; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::pasteboard::PasteboardType; @@ -27,6 +26,8 @@ pub use controller::ViewController; pub mod traits; pub use traits::ViewDelegate; +pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr"; + /// 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. @@ -37,7 +38,7 @@ pub struct View { /// An internal callback pointer that we use in delegate loopbacks. Default implementations /// don't require this. - internal_callback_ptr: Option<*const RefCell>, + pub(crate) internal_callback_ptr: Option<*const RefCell>, /// A pointer to the delegate for this view. pub delegate: Option>>, @@ -133,19 +134,7 @@ impl View where T: ViewDelegate + 'static { { let mut delegate = delegate.borrow_mut(); - (*delegate).did_load(View { - internal_callback_ptr: None, - delegate: None, - top: view.top.clone(), - leading: view.leading.clone(), - trailing: view.trailing.clone(), - bottom: view.bottom.clone(), - width: view.width.clone(), - height: view.height.clone(), - center_x: view.center_x.clone(), - center_y: view.center_y.clone(), - objc: view.objc.clone() - }); + (*delegate).did_load(view.clone_as_handle()); } view.delegate = Some(delegate); @@ -154,6 +143,26 @@ impl View where T: ViewDelegate + 'static { } impl View { + /// An internal method that returns a clone of this object, sans references to the delegate or + /// callback pointer. We use this in calling `did_load()` - implementing delegates get a way to + /// reference, customize and use the view but without the trickery of holding pieces of the + /// delegate - the `View` is the only true holder of those. + pub(crate) fn clone_as_handle(&self) -> View { + View { + internal_callback_ptr: None, + delegate: None, + top: self.top.clone(), + leading: self.leading.clone(), + 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(), + objc: self.objc.clone() + } + } + /// Call this to set the background color for the backing layer. pub fn set_background_color(&self, color: Color) { let bg = color.into_platform_specific_color(); @@ -162,9 +171,6 @@ impl View { let cg: id = msg_send![bg, CGColor]; let layer: id = msg_send![&*self.objc, layer]; let _: () = msg_send![layer, setBackgroundColor:cg]; - //let view: id = msg_send![*self.objc, view]; - //(*view).set_ivar(BACKGROUND_COLOR, color.into_platform_specific_color()); - //let _: () = msg_send![view, setNeedsDisplay:YES]; } } @@ -181,18 +187,6 @@ impl View { let _: () = msg_send![&*self.objc, registerForDraggedTypes:types.into_inner()]; } } - - //pub fn add_subview(&self, subview: &L) { - /*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]; - } - }*/ - //} } impl Layout for View { @@ -212,7 +206,7 @@ impl Layout for View { impl Drop for View { /// A bit of extra cleanup for delegate callback pointers. fn drop(&mut self) { - if let ptr = &self.internal_callback_ptr { + if let Some(ptr) = &self.internal_callback_ptr { unsafe { let _ = Rc::from_raw(ptr); } diff --git a/appkit/window/controller/mod.rs b/appkit/window/controller/mod.rs index 412cc8a..ca4552b 100644 --- a/appkit/window/controller/mod.rs +++ b/appkit/window/controller/mod.rs @@ -4,7 +4,7 @@ use objc::{msg_send, sel, sel_impl}; use objc_id::ShareId; use crate::foundation::{id, nil}; -use crate::layout::traits::Layout; +use crate::utils::Controller; use crate::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR}; mod class; @@ -51,9 +51,13 @@ impl WindowController where T: WindowDelegate + 'static { } } - /// Sets the content view controller for the window. - pub fn set_content_view_controller(&self, view_controller: &VC) { - //self.objc_controller.set_content_view_controller(view_controller); + /// Given a view, sets it as the content view controller for this window. + pub fn set_content_view_controller(&self, controller: &C) { + let backing_node = controller.get_backing_node(); + + unsafe { + let _: () = msg_send![&*self.objc, setContentViewController:&*backing_node]; + } } /// Shows the window, running a configuration pass if necessary. diff --git a/appkit/window/mod.rs b/appkit/window/mod.rs index deed6b0..ab1ab51 100644 --- a/appkit/window/mod.rs +++ b/appkit/window/mod.rs @@ -11,6 +11,7 @@ use objc_id::ShareId; use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, CGRect, CGSize}; use crate::layout::traits::Layout; use crate::toolbar::{Toolbar, ToolbarController}; +use crate::utils::Controller; mod class; use class::{register_window_class, register_window_class_with_delegate}; @@ -146,15 +147,6 @@ impl Window { } } - /// Used for setting the content view controller for this window. - pub fn set_content_view_controller(&self, view_controller: &L) { - //unsafe { - // if let Some(vc) = view_controller.get_backing_node() { - // let _: () = msg_send![*controller, setContentViewController:&*vc]; - // } - //} - } - /// Given a view, sets it as the content view for this window. pub fn set_content_view(&self, view: &L) { let backing_node = view.get_backing_node(); @@ -164,6 +156,15 @@ impl Window { } } + /// Given a view, sets it as the content view controller for this window. + pub fn set_content_view_controller(&self, controller: &C) { + let backing_node = controller.get_backing_node(); + + unsafe { + let _: () = msg_send![&*self.objc, setContentViewController:&*backing_node]; + } + } + /// Shows the window. pub fn show(&self) { unsafe {