Clean up warnings, finish moving View/ViewController to new paradigm, general cleanup - need to rewrite docs

This commit is contained in:
Ryan McGrath 2020-03-20 15:03:19 -07:00
parent fc53848ba2
commit c1da7b1b37
No known key found for this signature in database
GPG key ID: 811674B62B666830
11 changed files with 77 additions and 89 deletions

View file

@ -5,7 +5,6 @@
use std::sync::Once; use std::sync::Once;
use objc::class; use objc::class;
//, msg_send, sel, sel_impl};
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class}; use objc::runtime::{Class};

View file

@ -14,10 +14,10 @@ use objc::runtime::{Class, Object, Sel};
use url::Url; 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::app::traits::AppDelegate;
use crate::constants::APP_PTR;
use crate::error::AppKitError; use crate::error::AppKitError;
use crate::foundation::{id, nil, BOOL, YES, NO, NSUInteger, NSArray, NSString};
use crate::printing::PrintSettings; use crate::printing::PrintSettings;
use crate::user_activity::UserActivity; use crate::user_activity::UserActivity;

View file

@ -6,7 +6,6 @@ use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, YES, NO, NSUInteger, AutoReleasePool}; use crate::foundation::{id, YES, NO, NSUInteger, AutoReleasePool};
use crate::constants::APP_PTR;
use crate::menu::Menu; use crate::menu::Menu;
mod class; mod class;
@ -21,6 +20,8 @@ pub use enums::AppDelegateResponse;
pub mod traits; pub mod traits;
pub use traits::{AppDelegate, Dispatcher}; pub use traits::{AppDelegate, Dispatcher};
pub(crate) static APP_PTR: &str = "rstAppPtr";
/// A handler to make some boilerplate less annoying. /// A handler to make some boilerplate less annoying.
#[inline] #[inline]
fn shared_application<F: Fn(id)>(handler: F) { fn shared_application<F: Fn(id)>(handler: F) {

View file

@ -1,10 +1,7 @@
//! Constants typically used for referencing around in the Objective-C runtime. //! Constants typically used for referencing around in the Objective-C runtime.
//! Specific to this crate. //! 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 TOOLBAR_PTR: &str = "rstToolbarPtr";
pub(crate) static VIEW_DELEGATE_PTR: &str = "rstViewDelegatePtr";
#[cfg(feature = "webview")] #[cfg(feature = "webview")]
pub(crate) static WEBVIEW_CONFIG_VAR: &str = "rstWebViewConfig"; pub(crate) static WEBVIEW_CONFIG_VAR: &str = "rstWebViewConfig";

View file

@ -6,6 +6,13 @@ use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use objc::runtime::Object; 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<Object>;
}
/// Used for moving a pointer back into an Rc, so we can work with the object held behind it. Note /// 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 /// that it's very important to make sure you reverse this when you're done (using

View file

@ -12,13 +12,12 @@ use std::sync::Once;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; 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 objc_id::Id;
use crate::foundation::{id, nil, YES, NO, NSUInteger}; use crate::foundation::{id, YES, NO, NSUInteger};
use crate::constants::{BACKGROUND_COLOR, VIEW_DELEGATE_PTR};
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::view::traits::ViewDelegate; use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate};
use crate::utils::load; use crate::utils::load;
/// Enforces normalcy, or: a needlessly cruel method in terms of the name. You get the idea though. /// 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; 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. /// Called when a drag/drop operation has entered this view.
extern fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger { extern fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
let view = load::<T>(this, VIEW_DELEGATE_PTR); let view = load::<T>(this, VIEW_DELEGATE_PTR);
@ -132,10 +118,7 @@ pub(crate) fn register_view_class() -> *const Class {
let superclass = class!(NSView); let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
decl.add_ivar::<id>(BACKGROUND_COLOR);
decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); 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(); VIEW_CLASS = decl.register();
}); });
@ -156,11 +139,8 @@ pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Cla
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR); decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
decl.add_ivar::<id>(BACKGROUND_COLOR);
decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); 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) // Drag and drop operations (e.g, accepting files)
decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern fn (&mut Object, _, _) -> NSUInteger); decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern fn (&mut Object, _, _) -> NSUInteger);

View file

@ -7,8 +7,7 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use crate::constants::VIEW_DELEGATE_PTR; use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate};
use crate::view::traits::ViewDelegate;
use crate::utils::load; use crate::utils::load;
/// Called when the view controller receives a `viewWillAppear` message. /// Called when the view controller receives a `viewWillAppear` message.

View file

@ -1,36 +1,42 @@
use std::rc::Rc;
use std::cell::RefCell;
use objc_id::ShareId; use objc_id::ShareId;
use objc::runtime::Object; use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, NO}; use crate::foundation::id;
use crate::constants::VIEW_DELEGATE_PTR;
use crate::layout::{Layout}; use crate::layout::{Layout};
use crate::view::traits::ViewDelegate; use crate::view::{VIEW_DELEGATE_PTR, View, ViewDelegate};
mod class; mod class;
use class::register_view_controller_class; use class::register_view_controller_class;
//#[derive(Debug)] //#[derive(Debug)]
pub struct ViewController { pub struct ViewController<T> {
pub objc: ShareId<Object>, pub objc: ShareId<Object>,
pub view: Box<dyn ViewDelegate> pub view: View<T>
} }
impl ViewController { impl<T> ViewController<T> where T: ViewDelegate + 'static {
pub fn new<T: ViewDelegate + Layout + 'static>(view: T) -> Self { pub fn new(delegate: T) -> Self {
let view = Box::new(view); let mut view = View::with(delegate);
let objc = unsafe { let objc = unsafe {
let vc: id = msg_send![register_view_controller_class::<T>(), new]; let vc: id = msg_send![register_view_controller_class::<T>(), new];
let _: () = msg_send![vc, setView:&*view.get_backing_node()];
let ptr: *const T = &*view; if let Some(ptr)= view.internal_callback_ptr {
(&mut *vc).set_ivar(VIEW_DELEGATE_PTR, ptr as usize); (&mut *vc).set_ivar(VIEW_DELEGATE_PTR, ptr as usize);
}
let _: () = msg_send![vc, setView:&*view.get_backing_node()];
ShareId::from_ptr(vc) 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 { ViewController {
objc: objc, objc: objc,
view: view view: view

View file

@ -14,7 +14,6 @@ use objc::{msg_send, sel, sel_impl};
use crate::foundation::{id, YES, NO, NSArray, NSString}; use crate::foundation::{id, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::constants::{BACKGROUND_COLOR, VIEW_DELEGATE_PTR};
use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::{Layout, LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension};
use crate::pasteboard::PasteboardType; use crate::pasteboard::PasteboardType;
@ -27,6 +26,8 @@ pub use controller::ViewController;
pub mod traits; pub mod traits;
pub use traits::ViewDelegate; 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 /// 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.
@ -37,7 +38,7 @@ pub struct View<T = ()> {
/// An internal callback pointer that we use in delegate loopbacks. Default implementations /// An internal callback pointer that we use in delegate loopbacks. Default implementations
/// don't require this. /// don't require this.
internal_callback_ptr: Option<*const RefCell<T>>, pub(crate) internal_callback_ptr: Option<*const RefCell<T>>,
/// A pointer to the delegate for this view. /// A pointer to the delegate for this view.
pub delegate: Option<Rc<RefCell<T>>>, pub delegate: Option<Rc<RefCell<T>>>,
@ -133,19 +134,7 @@ impl<T> View<T> where T: ViewDelegate + 'static {
{ {
let mut delegate = delegate.borrow_mut(); let mut delegate = delegate.borrow_mut();
(*delegate).did_load(View { (*delegate).did_load(view.clone_as_handle());
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()
});
} }
view.delegate = Some(delegate); view.delegate = Some(delegate);
@ -154,6 +143,26 @@ impl<T> View<T> where T: ViewDelegate + 'static {
} }
impl<T> View<T> { impl<T> View<T> {
/// 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. /// 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) {
let bg = color.into_platform_specific_color(); let bg = color.into_platform_specific_color();
@ -162,9 +171,6 @@ impl<T> View<T> {
let cg: id = msg_send![bg, CGColor]; let cg: id = msg_send![bg, CGColor];
let layer: id = msg_send![&*self.objc, layer]; let layer: id = msg_send![&*self.objc, layer];
let _: () = msg_send![layer, setBackgroundColor:cg]; 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<T> View<T> {
let _: () = msg_send![&*self.objc, registerForDraggedTypes:types.into_inner()]; let _: () = msg_send![&*self.objc, registerForDraggedTypes:types.into_inner()];
} }
} }
//pub fn add_subview<L: Layout>(&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<T> Layout for View<T> { impl<T> Layout for View<T> {
@ -212,7 +206,7 @@ impl<T> Layout for View<T> {
impl<T> Drop for View<T> { impl<T> Drop for View<T> {
/// A bit of extra cleanup for delegate callback pointers. /// A bit of extra cleanup for delegate callback pointers.
fn drop(&mut self) { fn drop(&mut self) {
if let ptr = &self.internal_callback_ptr { if let Some(ptr) = &self.internal_callback_ptr {
unsafe { unsafe {
let _ = Rc::from_raw(ptr); let _ = Rc::from_raw(ptr);
} }

View file

@ -4,7 +4,7 @@ use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil}; use crate::foundation::{id, nil};
use crate::layout::traits::Layout; use crate::utils::Controller;
use crate::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR}; use crate::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
mod class; mod class;
@ -51,9 +51,13 @@ impl<T> WindowController<T> where T: WindowDelegate + 'static {
} }
} }
/// Sets the content view controller for the window. /// Given a view, sets it as the content view controller for this window.
pub fn set_content_view_controller<VC: Layout + 'static>(&self, view_controller: &VC) { pub fn set_content_view_controller<C: Controller + 'static>(&self, controller: &C) {
//self.objc_controller.set_content_view_controller(view_controller); 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. /// Shows the window, running a configuration pass if necessary.

View file

@ -11,6 +11,7 @@ use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, CGRect, CGSize}; use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger, CGRect, CGSize};
use crate::layout::traits::Layout; use crate::layout::traits::Layout;
use crate::toolbar::{Toolbar, ToolbarController}; use crate::toolbar::{Toolbar, ToolbarController};
use crate::utils::Controller;
mod class; mod class;
use class::{register_window_class, register_window_class_with_delegate}; use class::{register_window_class, register_window_class_with_delegate};
@ -146,15 +147,6 @@ impl<T> Window<T> {
} }
} }
/// Used for setting the content view controller for this window.
pub fn set_content_view_controller<L: Layout + 'static>(&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. /// Given a view, sets it as the content view for this window.
pub fn set_content_view<L: Layout + 'static>(&self, view: &L) { pub fn set_content_view<L: Layout + 'static>(&self, view: &L) {
let backing_node = view.get_backing_node(); let backing_node = view.get_backing_node();
@ -164,6 +156,15 @@ impl<T> Window<T> {
} }
} }
/// Given a view, sets it as the content view controller for this window.
pub fn set_content_view_controller<C: Controller + 'static>(&self, controller: &C) {
let backing_node = controller.get_backing_node();
unsafe {
let _: () = msg_send![&*self.objc, setContentViewController:&*backing_node];
}
}
/// Shows the window. /// Shows the window.
pub fn show(&self) { pub fn show(&self) {
unsafe { unsafe {