Initial conversion to objc2
(#30)
* Use objc2 * Replace `objc_id` * Remove sel_impl import * Fix `add_method` calls * Fix accessing raw FFI functions * Fix Encode impl * Fix message sends arguments that do not implement `Encode` * Use immutable reference in a few places where now necessary See https://github.com/madsmtm/objc2/pull/150 for a bit of background * Add a few Send + Sync bounds where examples require it This is something we'll need to look into properly * Use `&'static Class` instead of `*const Class` Safer and more ergonomic. Also required for `msg_send_id!` macro * Use msg_send_id! and rc::Id * Update objc2 to v0.3.0-beta.2 * Replace `BOOL` with `Bool` when declaring delegates This makes cacao compile on Aarch64 again * Remove a few impossible to use correctly `into_inner` functions These consumed `self`, and hence also dropped `Id` variable that was responsible for keeping the returned pointer alive * Remove a few impossible to use correctly `From` implementations * Quickly fix UB with using BACKGROUND_COLOR ivar * Fix double-freeing of windows * Fix double freeing of strings * Fix a few remaining double-frees
This commit is contained in:
parent
4f40d62623
commit
094ed59a04
|
@ -209,9 +209,7 @@ impl View {
|
||||||
center_x: LayoutAnchorX::center(view),
|
center_x: LayoutAnchorX::center(view),
|
||||||
center_y: LayoutAnchorY::center(view),
|
center_y: LayoutAnchorY::center(view),
|
||||||
|
|
||||||
layer: Layer::wrap(unsafe {
|
layer: Layer::from_id(unsafe { msg_send_id![view, layer] }),
|
||||||
msg_send![view, layer]
|
|
||||||
}),
|
|
||||||
|
|
||||||
objc: ObjcProperty::retain(view),
|
objc: ObjcProperty::retain(view),
|
||||||
}
|
}
|
||||||
|
@ -293,7 +291,8 @@ impl<T> View<T> {
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
(&mut *obj).set_ivar(BACKGROUND_COLOR, color);
|
// TODO: Fix this unnecessary retain!
|
||||||
|
(&mut *obj).set_ivar::<id>(BACKGROUND_COLOR, msg_send![color, retain]);
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
|
@ -352,22 +351,22 @@ We'll step through an example (abridged) `View` bridge below, for macOS. You sho
|
||||||
For our basic `View` type, we want to just map to the corresponding class on the Objective-C side (in this case, `NSView`), and maybe do a bit of tweaking for sanity reasons.
|
For our basic `View` type, we want to just map to the corresponding class on the Objective-C side (in this case, `NSView`), and maybe do a bit of tweaking for sanity reasons.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
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_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||||
|
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -377,19 +376,19 @@ Objective-C method signatures, as well as provision space for variable storage (
|
||||||
For our _delegate_ types, we need a different class creation method - one that creates a subclass per-unique-type:
|
For our _delegate_ types, we need a different class creation method - one that creates a subclass per-unique-type:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSView", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSView", instance.subclass_name(), |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(isFlipped),
|
sel!(isFlipped),
|
||||||
enforce_normalcy as extern "C" fn(&Object, _) -> BOOL
|
enforce_normalcy as extern "C" fn(_, _) -> _,
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(draggingEntered:),
|
sel!(draggingEntered:),
|
||||||
dragging_entered::<T> as extern "C" fn (&mut Object, _, _) -> NSUInteger
|
dragging_entered::<T> as extern "C" fn (_, _, _) -> _,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -401,18 +400,18 @@ to the Rust `ViewDelegate` implementation.
|
||||||
The methods we're setting up can range from simple to complex - take `isFlipped`:
|
The methods we're setting up can range from simple to complex - take `isFlipped`:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
extern "C" fn is_flipped(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn is_flipped(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, we just want to tell `NSView` to use top,left as the origin point, so we need to respond `YES` in this subclass method.
|
Here, we just want to tell `NSView` to use top,left as the origin point, so we need to respond `Bool::YES` in this subclass method.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
extern "C" fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
extern "C" fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
||||||
let view = utils::load::<T>(this, VIEW_DELEGATE_PTR);
|
let view = utils::load::<T>(this, VIEW_DELEGATE_PTR);
|
||||||
view.dragging_entered(DragInfo {
|
view.dragging_entered(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}).into()
|
}).into()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -20,15 +20,16 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitmask-enum = "2.2.1"
|
bitmask-enum = "2.2.1"
|
||||||
block = "0.1.6"
|
objc = { version = "=0.3.0-beta.2", package = "objc2" }
|
||||||
core-foundation = "0.9"
|
block = { version = "=0.2.0-alpha.6", package = "block2" }
|
||||||
core-graphics = "0.23"
|
# Temporary: Patched versions that implement `Encode` for common types
|
||||||
|
# Branch: `objc2`
|
||||||
|
core-foundation = { git = "https://github.com/madsmtm/core-foundation-rs.git", rev = "7d593d016175755e492a92ef89edca68ac3bd5cd" }
|
||||||
|
core-graphics = { git = "https://github.com/madsmtm/core-foundation-rs.git", rev = "7d593d016175755e492a92ef89edca68ac3bd5cd" }
|
||||||
dispatch = "0.2.0"
|
dispatch = "0.2.0"
|
||||||
infer = { version = "0.15", optional = true }
|
infer = { version = "0.15", optional = true }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
objc = "0.2.7"
|
|
||||||
objc_id = "0.1.1"
|
|
||||||
os_info = "3.0.1"
|
os_info = "3.0.1"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
uuid = { version = "1.1", features = ["v4"], optional = true }
|
uuid = { version = "1.1", features = ["v4"], optional = true }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use cacao::objc::{msg_send, sel, sel_impl};
|
use cacao::objc::{msg_send, sel};
|
||||||
|
|
||||||
use cacao::button::Button;
|
use cacao::button::Button;
|
||||||
use cacao::input::{TextField, TextFieldDelegate};
|
use cacao::input::{TextField, TextFieldDelegate};
|
||||||
|
@ -35,12 +35,12 @@ impl BrowserToolbar {
|
||||||
let back_button = Button::new("Back");
|
let back_button = Button::new("Back");
|
||||||
let mut back_item = ToolbarItem::new(BACK_BUTTON);
|
let mut back_item = ToolbarItem::new(BACK_BUTTON);
|
||||||
back_item.set_button(back_button);
|
back_item.set_button(back_button);
|
||||||
back_item.set_action(|| Action::Back.dispatch());
|
back_item.set_action(|_| Action::Back.dispatch());
|
||||||
|
|
||||||
let forwards_button = Button::new("Forwards");
|
let forwards_button = Button::new("Forwards");
|
||||||
let mut forwards_item = ToolbarItem::new(FWDS_BUTTON);
|
let mut forwards_item = ToolbarItem::new(FWDS_BUTTON);
|
||||||
forwards_item.set_button(forwards_button);
|
forwards_item.set_button(forwards_button);
|
||||||
forwards_item.set_action(|| Action::Forwards.dispatch());
|
forwards_item.set_action(|_| Action::Forwards.dispatch());
|
||||||
|
|
||||||
let url_bar = TextField::with(URLBar);
|
let url_bar = TextField::with(URLBar);
|
||||||
let url_bar_item = ToolbarItem::new(URL_BAR);
|
let url_bar_item = ToolbarItem::new(URL_BAR);
|
||||||
|
|
|
@ -24,16 +24,16 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
|
|
||||||
/// Represents an `NSAlert`. Has no information other than the retained pointer to the Objective C
|
/// Represents an `NSAlert`. Has no information other than the retained pointer to the Objective C
|
||||||
/// side, so... don't bother inspecting this.
|
/// side, so... don't bother inspecting this.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Alert(Id<Object>);
|
pub struct Alert(Id<Object, Owned>);
|
||||||
|
|
||||||
impl Alert {
|
impl Alert {
|
||||||
/// Creates a basic `NSAlert`, storing a pointer to it in the Objective C runtime.
|
/// Creates a basic `NSAlert`, storing a pointer to it in the Objective C runtime.
|
||||||
|
@ -44,11 +44,11 @@ impl Alert {
|
||||||
let ok = NSString::new("OK");
|
let ok = NSString::new("OK");
|
||||||
|
|
||||||
Alert(unsafe {
|
Alert(unsafe {
|
||||||
let alert: id = msg_send![class!(NSAlert), new];
|
let mut alert = msg_send_id![class!(NSAlert), new];
|
||||||
let _: () = msg_send![alert, setMessageText: title];
|
let _: () = msg_send![&mut alert, setMessageText: &*title];
|
||||||
let _: () = msg_send![alert, setInformativeText: message];
|
let _: () = msg_send![&mut alert, setInformativeText: &*message];
|
||||||
let _: () = msg_send![alert, addButtonWithTitle: ok];
|
let _: () = msg_send![&mut alert, addButtonWithTitle: &*ok];
|
||||||
Id::from_ptr(alert)
|
alert
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl AnimationContext {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
//let context: id = msg_send![class!(NSAnimationContext), currentContext];
|
//let context: id = msg_send![class!(NSAnimationContext), currentContext];
|
||||||
let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup: block];
|
let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup: &*block];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +66,11 @@ impl AnimationContext {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
//let context: id = msg_send![class!(NSAnimationContext), currentContext];
|
//let context: id = msg_send![class!(NSAnimationContext), currentContext];
|
||||||
let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup:block
|
let _: () = msg_send![
|
||||||
completionHandler:completion_block];
|
class!(NSAnimationContext),
|
||||||
|
runAnimationGroup: &*block,
|
||||||
|
completionHandler: &*completion_block,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,6 @@ use objc::runtime::Class;
|
||||||
use crate::foundation::load_or_register_class;
|
use crate::foundation::load_or_register_class;
|
||||||
|
|
||||||
/// Used for injecting a custom NSApplication. Currently does nothing.
|
/// Used for injecting a custom NSApplication. Currently does nothing.
|
||||||
pub(crate) fn register_app_class() -> *const Class {
|
pub(crate) fn register_app_class() -> &'static Class {
|
||||||
load_or_register_class("NSApplication", "RSTApplication", |decl| unsafe {})
|
load_or_register_class("NSApplication", "RSTApplication", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
use block::Block;
|
use block::Block;
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::appkit::app::{AppDelegate, APP_PTR};
|
use crate::appkit::app::{AppDelegate, APP_PTR};
|
||||||
|
@ -14,7 +14,7 @@ use crate::appkit::printing::PrintSettings;
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
use crate::cloudkit::share::CKShareMetaData;
|
use crate::cloudkit::share::CKShareMetaData;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::foundation::{id, load_or_register_class, nil, to_bool, NSArray, NSString, NSUInteger, BOOL, NO, YES};
|
use crate::foundation::{id, load_or_register_class, nil, NSArray, NSString, NSUInteger};
|
||||||
use crate::user_activity::UserActivity;
|
use crate::user_activity::UserActivity;
|
||||||
|
|
||||||
/// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our
|
/// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our
|
||||||
|
@ -99,11 +99,8 @@ extern "C" fn did_update<T: AppDelegate>(this: &Object, _: Sel, _: id) {
|
||||||
|
|
||||||
/// Fires when the Application Delegate receives a
|
/// Fires when the Application Delegate receives a
|
||||||
/// `applicationShouldHandleReopen:hasVisibleWindows:` notification.
|
/// `applicationShouldHandleReopen:hasVisibleWindows:` notification.
|
||||||
extern "C" fn should_handle_reopen<T: AppDelegate>(this: &Object, _: Sel, _: id, has_visible_windows: BOOL) -> BOOL {
|
extern "C" fn should_handle_reopen<T: AppDelegate>(this: &Object, _: Sel, _: id, has_visible_windows: Bool) -> Bool {
|
||||||
match app::<T>(this).should_handle_reopen(to_bool(has_visible_windows)) {
|
Bool::new(app::<T>(this).should_handle_reopen(has_visible_windows.as_bool()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fires when the application delegate receives a `applicationDockMenu:` request.
|
/// Fires when the application delegate receives a `applicationDockMenu:` request.
|
||||||
|
@ -128,29 +125,23 @@ extern "C" fn did_change_screen_parameters<T: AppDelegate>(this: &Object, _: Sel
|
||||||
|
|
||||||
/// Fires when the application receives a `application:willContinueUserActivityWithType:`
|
/// Fires when the application receives a `application:willContinueUserActivityWithType:`
|
||||||
/// notification.
|
/// notification.
|
||||||
extern "C" fn will_continue_user_activity_with_type<T: AppDelegate>(this: &Object, _: Sel, _: id, activity_type: id) -> BOOL {
|
extern "C" fn will_continue_user_activity_with_type<T: AppDelegate>(this: &Object, _: Sel, _: id, activity_type: id) -> Bool {
|
||||||
let activity = NSString::retain(activity_type);
|
let activity = NSString::retain(activity_type);
|
||||||
|
|
||||||
match app::<T>(this).will_continue_user_activity(activity.to_str()) {
|
Bool::new(app::<T>(this).will_continue_user_activity(activity.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fires when the application receives a `application:continueUserActivity:restorationHandler:` notification.
|
/// Fires when the application receives a `application:continueUserActivity:restorationHandler:` notification.
|
||||||
extern "C" fn continue_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity: id, handler: id) -> BOOL {
|
extern "C" fn continue_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity: id, handler: id) -> Bool {
|
||||||
// @TODO: This needs to support restorable objects, but it involves a larger question about how
|
// @TODO: This needs to support restorable objects, but it involves a larger question about how
|
||||||
// much `NSObject` retainping we want to do here. For now, pass the handler for whenever it's
|
// much `NSObject` retainping we want to do here. For now, pass the handler for whenever it's
|
||||||
// useful.
|
// useful.
|
||||||
let activity = UserActivity::with_inner(activity);
|
let activity = UserActivity::with_inner(activity);
|
||||||
|
|
||||||
match app::<T>(this).continue_user_activity(activity, || unsafe {
|
Bool::new(app::<T>(this).continue_user_activity(activity, || unsafe {
|
||||||
let handler = handler as *const Block<(id,), c_void>;
|
let handler = handler as *const Block<(id,), ()>;
|
||||||
(*handler).call((nil,));
|
(*handler).call((nil,));
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fires when the application receives a
|
/// Fires when the application receives a
|
||||||
|
@ -199,57 +190,39 @@ extern "C" fn open_urls<T: AppDelegate>(this: &Object, _: Sel, _: id, file_urls:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fires when the application receives an `application:openFileWithoutUI:` message.
|
/// Fires when the application receives an `application:openFileWithoutUI:` message.
|
||||||
extern "C" fn open_file_without_ui<T: AppDelegate>(this: &Object, _: Sel, _: id, file: id) -> BOOL {
|
extern "C" fn open_file_without_ui<T: AppDelegate>(this: &Object, _: Sel, _: id, file: id) -> Bool {
|
||||||
let filename = NSString::retain(file);
|
let filename = NSString::retain(file);
|
||||||
|
|
||||||
match app::<T>(this).open_file_without_ui(filename.to_str()) {
|
Bool::new(app::<T>(this).open_file_without_ui(filename.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `applicationShouldOpenUntitledFile:` message.
|
/// Fired when the application receives an `applicationShouldOpenUntitledFile:` message.
|
||||||
extern "C" fn should_open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn should_open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id) -> Bool {
|
||||||
match app::<T>(this).should_open_untitled_file() {
|
Bool::new(app::<T>(this).should_open_untitled_file())
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `applicationShouldTerminateAfterLastWindowClosed:` message.
|
/// Fired when the application receives an `applicationShouldTerminateAfterLastWindowClosed:` message.
|
||||||
extern "C" fn should_terminate_after_last_window_closed<T: AppDelegate>(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn should_terminate_after_last_window_closed<T: AppDelegate>(this: &Object, _: Sel, _: id) -> Bool {
|
||||||
match app::<T>(this).should_terminate_after_last_window_closed() {
|
Bool::new(app::<T>(this).should_terminate_after_last_window_closed())
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `applicationOpenUntitledFile:` message.
|
/// Fired when the application receives an `applicationOpenUntitledFile:` message.
|
||||||
extern "C" fn open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id) -> Bool {
|
||||||
match app::<T>(this).open_untitled_file() {
|
Bool::new(app::<T>(this).open_untitled_file())
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `application:openTempFile:` message.
|
/// Fired when the application receives an `application:openTempFile:` message.
|
||||||
extern "C" fn open_temp_file<T: AppDelegate>(this: &Object, _: Sel, _: id, filename: id) -> BOOL {
|
extern "C" fn open_temp_file<T: AppDelegate>(this: &Object, _: Sel, _: id, filename: id) -> Bool {
|
||||||
let filename = NSString::retain(filename);
|
let filename = NSString::retain(filename);
|
||||||
|
|
||||||
match app::<T>(this).open_temp_file(filename.to_str()) {
|
Bool::new(app::<T>(this).open_temp_file(filename.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `application:printFile:` message.
|
/// Fired when the application receives an `application:printFile:` message.
|
||||||
extern "C" fn print_file<T: AppDelegate>(this: &Object, _: Sel, _: id, file: id) -> BOOL {
|
extern "C" fn print_file<T: AppDelegate>(this: &Object, _: Sel, _: id, file: id) -> Bool {
|
||||||
let filename = NSString::retain(file);
|
let filename = NSString::retain(file);
|
||||||
|
|
||||||
match app::<T>(this).print_file(filename.to_str()) {
|
Bool::new(app::<T>(this).print_file(filename.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fired when the application receives an `application:printFiles:withSettings:showPrintPanels:`
|
/// Fired when the application receives an `application:printFiles:withSettings:showPrintPanels:`
|
||||||
|
@ -260,7 +233,7 @@ extern "C" fn print_files<T: AppDelegate>(
|
||||||
_: id,
|
_: id,
|
||||||
files: id,
|
files: id,
|
||||||
settings: id,
|
settings: id,
|
||||||
show_print_panels: BOOL
|
show_print_panels: Bool
|
||||||
) -> NSUInteger {
|
) -> NSUInteger {
|
||||||
let files = NSArray::retain(files)
|
let files = NSArray::retain(files)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -269,7 +242,9 @@ extern "C" fn print_files<T: AppDelegate>(
|
||||||
|
|
||||||
let settings = PrintSettings::with_inner(settings);
|
let settings = PrintSettings::with_inner(settings);
|
||||||
|
|
||||||
app::<T>(this).print_files(files, settings, to_bool(show_print_panels)).into()
|
app::<T>(this)
|
||||||
|
.print_files(files, settings, show_print_panels.as_bool())
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the application's occlusion state has changed.
|
/// Called when the application's occlusion state has changed.
|
||||||
|
@ -280,168 +255,156 @@ extern "C" fn did_change_occlusion_state<T: AppDelegate>(this: &Object, _: Sel,
|
||||||
/// Called when the application receives an `application:delegateHandlesKey:` message.
|
/// Called when the application receives an `application:delegateHandlesKey:` message.
|
||||||
/// Note: this may not fire in sandboxed applications. Apple's documentation is unclear on the
|
/// Note: this may not fire in sandboxed applications. Apple's documentation is unclear on the
|
||||||
/// matter.
|
/// matter.
|
||||||
extern "C" fn delegate_handles_key<T: AppDelegate>(this: &Object, _: Sel, _: id, key: id) -> BOOL {
|
extern "C" fn delegate_handles_key<T: AppDelegate>(this: &Object, _: Sel, _: id, key: id) -> Bool {
|
||||||
let key = NSString::retain(key);
|
let key = NSString::retain(key);
|
||||||
|
|
||||||
match app::<T>(this).delegate_handles_key(key.to_str()) {
|
Bool::new(app::<T>(this).delegate_handles_key(key.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
||||||
/// pointers we need to have.
|
/// pointers we need to have.
|
||||||
pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class {
|
pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> &'static Class {
|
||||||
load_or_register_class("NSObject", "RSTAppDelegate", |decl| unsafe {
|
load_or_register_class("NSObject", "RSTAppDelegate", |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(APP_PTR);
|
decl.add_ivar::<usize>(APP_PTR);
|
||||||
|
|
||||||
// Launching Applications
|
// Launching Applications
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationWillFinishLaunching:),
|
sel!(applicationWillFinishLaunching:),
|
||||||
will_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
will_finish_launching::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidFinishLaunching:),
|
sel!(applicationDidFinishLaunching:),
|
||||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
did_finish_launching::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Managing Active Status
|
// Managing Active Status
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationWillBecomeActive:),
|
sel!(applicationWillBecomeActive:),
|
||||||
will_become_active::<T> as extern "C" fn(&Object, _, _)
|
will_become_active::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidBecomeActive:),
|
sel!(applicationDidBecomeActive:),
|
||||||
did_become_active::<T> as extern "C" fn(&Object, _, _)
|
did_become_active::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationWillResignActive:),
|
sel!(applicationWillResignActive:),
|
||||||
will_resign_active::<T> as extern "C" fn(&Object, _, _)
|
will_resign_active::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidResignActive:),
|
sel!(applicationDidResignActive:),
|
||||||
did_resign_active::<T> as extern "C" fn(&Object, _, _)
|
did_resign_active::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Terminating Applications
|
// Terminating Applications
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationShouldTerminate:),
|
sel!(applicationShouldTerminate:),
|
||||||
should_terminate::<T> as extern "C" fn(&Object, _, _) -> NSUInteger
|
should_terminate::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(applicationWillTerminate:),
|
|
||||||
will_terminate::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
);
|
||||||
|
decl.add_method(sel!(applicationWillTerminate:), will_terminate::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationShouldTerminateAfterLastWindowClosed:),
|
sel!(applicationShouldTerminateAfterLastWindowClosed:),
|
||||||
should_terminate_after_last_window_closed::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
should_terminate_after_last_window_closed::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hiding Applications
|
// Hiding Applications
|
||||||
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(_, _, _));
|
||||||
|
|
||||||
// Managing Windows
|
// Managing Windows
|
||||||
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
|
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
|
||||||
should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL
|
should_handle_reopen::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Dock Menu
|
// Dock Menu
|
||||||
decl.add_method(
|
decl.add_method(sel!(applicationDockMenu:), dock_menu::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(applicationDockMenu:),
|
|
||||||
dock_menu::<T> as extern "C" fn(&Object, _, _) -> id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Displaying Errors
|
// Displaying Errors
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:willPresentError:),
|
sel!(application:willPresentError:),
|
||||||
will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id
|
will_present_error::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Managing the Screen
|
// Managing the Screen
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidChangeScreenParameters:),
|
sel!(applicationDidChangeScreenParameters:),
|
||||||
did_change_screen_parameters::<T> as extern "C" fn(&Object, _, _)
|
did_change_screen_parameters::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationDidChangeOcclusionState:),
|
sel!(applicationDidChangeOcclusionState:),
|
||||||
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
|
did_change_occlusion_state::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// User Activities
|
// User Activities
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:willContinueUserActivityWithType:),
|
sel!(application:willContinueUserActivityWithType:),
|
||||||
will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
will_continue_user_activity_with_type::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:continueUserActivity:restorationHandler:),
|
sel!(application:continueUserActivity:restorationHandler:),
|
||||||
continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) -> BOOL
|
continue_user_activity::<T> as extern "C" fn(_, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didFailToContinueUserActivityWithType:error:),
|
sel!(application:didFailToContinueUserActivityWithType:error:),
|
||||||
failed_to_continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id)
|
failed_to_continue_user_activity::<T> as extern "C" fn(_, _, _, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didUpdateUserActivity:),
|
sel!(application:didUpdateUserActivity:),
|
||||||
did_update_user_activity::<T> as extern "C" fn(&Object, _, _, id)
|
did_update_user_activity::<T> as extern "C" fn(_, _, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handling push notifications
|
// Handling push notifications
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
|
sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
|
||||||
registered_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
registered_for_remote_notifications::<T> as extern "C" fn(_, _, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didFailToRegisterForRemoteNotificationsWithError:),
|
sel!(application:didFailToRegisterForRemoteNotificationsWithError:),
|
||||||
failed_to_register_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
failed_to_register_for_remote_notifications::<T> as extern "C" fn(_, _, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didReceiveRemoteNotification:),
|
sel!(application:didReceiveRemoteNotification:),
|
||||||
did_receive_remote_notification::<T> as extern "C" fn(&Object, _, _, id)
|
did_receive_remote_notification::<T> as extern "C" fn(_, _, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// CloudKit
|
// CloudKit
|
||||||
#[cfg(feature = "cloudkit")]
|
#[cfg(feature = "cloudkit")]
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:userDidAcceptCloudKitShareWithMetadata:),
|
sel!(application:userDidAcceptCloudKitShareWithMetadata:),
|
||||||
accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id)
|
accepted_cloudkit_share::<T> as extern "C" fn(_, _, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Opening Files
|
// Opening Files
|
||||||
decl.add_method(
|
decl.add_method(sel!(application:openURLs:), open_urls::<T> as extern "C" fn(_, _, _, _));
|
||||||
sel!(application:openURLs:),
|
|
||||||
open_urls::<T> as extern "C" fn(&Object, _, _, id)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:openFileWithoutUI:),
|
sel!(application:openFileWithoutUI:),
|
||||||
open_file_without_ui::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
open_file_without_ui::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationShouldOpenUntitledFile:),
|
sel!(applicationShouldOpenUntitledFile:),
|
||||||
should_open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
should_open_untitled_file::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(applicationOpenUntitledFile:),
|
sel!(applicationOpenUntitledFile:),
|
||||||
open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
open_untitled_file::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:openTempFile:),
|
sel!(application:openTempFile:),
|
||||||
open_temp_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
open_temp_file::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:printFile:),
|
sel!(application:printFile:),
|
||||||
print_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
print_file::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:printFiles:withSettings:showPrintPanels:),
|
sel!(application:printFiles:withSettings:showPrintPanels:),
|
||||||
print_files::<T> as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger
|
print_files::<T> as extern "C" fn(_, _, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// @TODO: Restoring Application State
|
// @TODO: Restoring Application State
|
||||||
|
@ -450,7 +413,7 @@ pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *co
|
||||||
// Scripting
|
// Scripting
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:delegateHandlesKey:),
|
sel!(application:delegateHandlesKey:),
|
||||||
delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
delegate_handles_key::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::appkit::menu::Menu;
|
use crate::appkit::menu::Menu;
|
||||||
use crate::foundation::{id, nil, AutoReleasePool, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, AutoReleasePool, NSUInteger, NO, YES};
|
||||||
|
@ -88,11 +88,11 @@ pub(crate) fn shared_application<T, F: Fn(id) -> T>(handler: F) -> T {
|
||||||
/// application.
|
/// application.
|
||||||
pub struct App<T = (), M = ()> {
|
pub struct App<T = (), M = ()> {
|
||||||
/// The underlying Objective-C Object.
|
/// The underlying Objective-C Object.
|
||||||
pub objc: Id<Object>,
|
pub objc: Id<Object, Owned>,
|
||||||
|
|
||||||
/// The underlying Objective-C Object, which in this case is a delegate that forwards to the
|
/// The underlying Objective-C Object, which in this case is a delegate that forwards to the
|
||||||
/// app delegate.
|
/// app delegate.
|
||||||
pub objc_delegate: Id<Object>,
|
pub objc_delegate: Id<Object, Owned>,
|
||||||
|
|
||||||
/// The stored `AppDelegate`.
|
/// The stored `AppDelegate`.
|
||||||
pub delegate: Box<T>,
|
pub delegate: Box<T>,
|
||||||
|
@ -144,20 +144,17 @@ where
|
||||||
|
|
||||||
let pool = AutoReleasePool::new();
|
let pool = AutoReleasePool::new();
|
||||||
|
|
||||||
let objc = unsafe {
|
let objc: Id<_, _> = unsafe { msg_send_id![register_app_class(), sharedApplication] };
|
||||||
let app: id = msg_send![register_app_class(), sharedApplication];
|
|
||||||
Id::from_ptr(app)
|
|
||||||
};
|
|
||||||
|
|
||||||
let app_delegate = Box::new(delegate);
|
let app_delegate = Box::new(delegate);
|
||||||
|
|
||||||
let objc_delegate = unsafe {
|
let objc_delegate = unsafe {
|
||||||
let delegate_class = register_app_delegate_class::<T>();
|
let delegate_class = register_app_delegate_class::<T>();
|
||||||
let delegate: id = msg_send![delegate_class, new];
|
let mut delegate: Id<Object, Owned> = msg_send_id![delegate_class, new];
|
||||||
let delegate_ptr: *const T = &*app_delegate;
|
let delegate_ptr: *const T = &*app_delegate;
|
||||||
(&mut *delegate).set_ivar(APP_PTR, delegate_ptr as usize);
|
delegate.set_ivar(APP_PTR, delegate_ptr as usize);
|
||||||
let _: () = msg_send![&*objc, setDelegate: delegate];
|
let _: () = msg_send![&*objc, setDelegate: &*delegate];
|
||||||
Id::from_ptr(delegate)
|
delegate
|
||||||
};
|
};
|
||||||
|
|
||||||
App {
|
App {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, NO, YES};
|
use crate::foundation::{id, NO, YES};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use bitmask_enum::bitmask;
|
use bitmask_enum::bitmask;
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use crate::foundation::{id, nil, NSInteger, NSPoint, NSString};
|
use crate::foundation::{id, nil, NSInteger, NSPoint, NSString};
|
||||||
|
@ -53,15 +53,15 @@ pub enum EventMask {
|
||||||
|
|
||||||
/// A wrapper over an `NSEvent`.
|
/// A wrapper over an `NSEvent`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EventMonitor(pub Id<Object>);
|
pub struct EventMonitor(pub Id<Object, Owned>);
|
||||||
|
|
||||||
/// A wrapper over an `NSEvent`.
|
/// A wrapper over an `NSEvent`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Event(pub Id<Object>);
|
pub struct Event(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Event {
|
impl Event {
|
||||||
pub(crate) fn new(objc: id) -> Self {
|
pub(crate) fn new(objc: id) -> Self {
|
||||||
Event(unsafe { Id::from_ptr(objc) })
|
Event(unsafe { Id::retain(objc).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The event's type.
|
/// The event's type.
|
||||||
|
@ -137,8 +137,11 @@ impl Event {
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
|
|
||||||
EventMonitor(unsafe {
|
EventMonitor(unsafe {
|
||||||
msg_send![class!(NSEvent), addLocalMonitorForEventsMatchingMask:mask.bits
|
msg_send_id![
|
||||||
handler:block]
|
class!(NSEvent),
|
||||||
|
addLocalMonitorForEventsMatchingMask: mask.bits,
|
||||||
|
handler: &*block,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,8 +166,11 @@ impl Event {
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
|
|
||||||
EventMonitor(unsafe {
|
EventMonitor(unsafe {
|
||||||
msg_send![class!(NSEvent), addGlobalMonitorForEventsMatchingMask:mask.bits
|
msg_send_id![
|
||||||
handler:block]
|
class!(NSEvent),
|
||||||
|
addGlobalMonitorForEventsMatchingMask: mask.bits,
|
||||||
|
handler: &*block,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
use objc::rc::{Id, Shared};
|
||||||
use objc_id::ShareId;
|
use objc::{class, msg_send, msg_send_id, runtime::Object, sel};
|
||||||
|
|
||||||
use crate::foundation::NSUInteger;
|
use crate::foundation::NSUInteger;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HapticFeedbackPerformer(pub ShareId<Object>);
|
pub struct HapticFeedbackPerformer(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl HapticFeedbackPerformer {
|
impl HapticFeedbackPerformer {
|
||||||
pub fn perform(&self, pattern: FeedbackPattern, performance_time: PerformanceTime) {
|
pub fn perform(&self, pattern: FeedbackPattern, performance_time: PerformanceTime) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, performFeedbackPattern: pattern performanceTime: performance_time];
|
let _: () = msg_send![&*self.0, performFeedbackPattern: pattern as isize performanceTime: performance_time as usize];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,7 @@ impl HapticFeedbackPerformer {
|
||||||
impl Default for HapticFeedbackPerformer {
|
impl Default for HapticFeedbackPerformer {
|
||||||
/// Returns the default haptic feedback performer.
|
/// Returns the default haptic feedback performer.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
HapticFeedbackPerformer(unsafe {
|
HapticFeedbackPerformer(unsafe { msg_send_id![class!(NSHapticFeedbackManager), defaultPerformer] })
|
||||||
let manager = msg_send![class!(NSHapticFeedbackManager), defaultPerformer];
|
|
||||||
ShareId::from_ptr(manager)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Class, Object, Sel};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::events::EventModifierFlag;
|
use crate::events::EventModifierFlag;
|
||||||
use crate::foundation::{id, load_or_register_class, NSString, NSUInteger};
|
use crate::foundation::{id, load_or_register_class, NSString, NSUInteger};
|
||||||
|
@ -37,7 +37,7 @@ fn make_menu_item<S: AsRef<str>>(
|
||||||
key: Option<&str>,
|
key: Option<&str>,
|
||||||
action: Option<Sel>,
|
action: Option<Sel>,
|
||||||
modifiers: Option<&[EventModifierFlag]>
|
modifiers: Option<&[EventModifierFlag]>
|
||||||
) -> Id<Object> {
|
) -> Id<Object, Owned> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let title = NSString::new(title.as_ref());
|
let title = NSString::new(title.as_ref());
|
||||||
|
|
||||||
|
@ -50,14 +50,21 @@ fn make_menu_item<S: AsRef<str>>(
|
||||||
// Stock menu items that use selectors targeted at system pieces are just standard
|
// Stock menu items that use selectors targeted at system pieces are just standard
|
||||||
// `NSMenuItem`s. If there's no custom ones, we use our subclass that has a slot to store a
|
// `NSMenuItem`s. If there's no custom ones, we use our subclass that has a slot to store a
|
||||||
// handler pointer.
|
// handler pointer.
|
||||||
let alloc: id = msg_send![register_menu_item_class(), alloc];
|
let alloc = msg_send_id![register_menu_item_class(), alloc];
|
||||||
let item = Id::from_retained_ptr(match action {
|
let item: Id<_, _> = match action {
|
||||||
Some(a) => msg_send![alloc, initWithTitle:&*title action:a keyEquivalent:&*key],
|
Some(a) => msg_send_id![
|
||||||
|
alloc,
|
||||||
None => msg_send![alloc, initWithTitle:&*title
|
initWithTitle: &*title,
|
||||||
action:sel!(fireBlockAction:)
|
action: a,
|
||||||
keyEquivalent:&*key]
|
keyEquivalent: &*key,
|
||||||
});
|
],
|
||||||
|
None => msg_send_id![
|
||||||
|
alloc,
|
||||||
|
initWithTitle: &*title,
|
||||||
|
action: sel!(fireBlockAction:),
|
||||||
|
keyEquivalent: &*key,
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(modifiers) = modifiers {
|
if let Some(modifiers) = modifiers {
|
||||||
let mut key_mask: NSUInteger = 0;
|
let mut key_mask: NSUInteger = 0;
|
||||||
|
@ -83,7 +90,7 @@ pub enum MenuItem {
|
||||||
/// You can (and should) create this variant via the `new(title)` method, but if you need to do
|
/// You can (and should) create this variant via the `new(title)` method, but if you need to do
|
||||||
/// something crazier, then wrap it in this and you can hook into the Cacao menu system
|
/// something crazier, then wrap it in this and you can hook into the Cacao menu system
|
||||||
/// accordingly.
|
/// accordingly.
|
||||||
Custom(Id<Object>),
|
Custom(Id<Object, Owned>),
|
||||||
|
|
||||||
/// Shows a standard "About" item, which will bring up the necessary window when clicked
|
/// Shows a standard "About" item, which will bring up the necessary window when clicked
|
||||||
/// (include a `credits.html` in your App to make use of here). The argument baked in here
|
/// (include a `credits.html` in your App to make use of here). The argument baked in here
|
||||||
|
@ -150,7 +157,7 @@ pub enum MenuItem {
|
||||||
impl MenuItem {
|
impl MenuItem {
|
||||||
/// Consumes and returns a handle for the underlying MenuItem. This is internal as we make a few assumptions
|
/// Consumes and returns a handle for the underlying MenuItem. This is internal as we make a few assumptions
|
||||||
/// for how it interacts with our `Menu` setup, but this could be made public in the future.
|
/// for how it interacts with our `Menu` setup, but this could be made public in the future.
|
||||||
pub(crate) unsafe fn to_objc(self) -> Id<Object> {
|
pub(crate) unsafe fn to_objc(self) -> Id<Object, Owned> {
|
||||||
match self {
|
match self {
|
||||||
Self::Custom(objc) => objc,
|
Self::Custom(objc) => objc,
|
||||||
|
|
||||||
|
@ -211,8 +218,7 @@ impl MenuItem {
|
||||||
|
|
||||||
Self::Separator => {
|
Self::Separator => {
|
||||||
let cls = class!(NSMenuItem);
|
let cls = class!(NSMenuItem);
|
||||||
let separator: id = msg_send![cls, separatorItem];
|
msg_send_id![cls, separatorItem]
|
||||||
Id::from_ptr(separator)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +235,7 @@ impl MenuItem {
|
||||||
if let MenuItem::Custom(objc) = self {
|
if let MenuItem::Custom(objc) = self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let key = NSString::new(key);
|
let key = NSString::new(key);
|
||||||
let _: () = msg_send![&*objc, setKeyEquivalent: key];
|
let _: () = msg_send![&*objc, setKeyEquivalent: &*key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return MenuItem::Custom(objc);
|
return MenuItem::Custom(objc);
|
||||||
|
@ -314,11 +320,11 @@ extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) {
|
||||||
///
|
///
|
||||||
/// In general, we do not want to do more than we need to here - menus are one of the last areas
|
/// In general, we do not want to do more than we need to here - menus are one of the last areas
|
||||||
/// where Carbon still lurks, and subclassing things can get weird.
|
/// where Carbon still lurks, and subclassing things can get weird.
|
||||||
pub(crate) fn register_menu_item_class() -> *const Class {
|
pub(crate) fn register_menu_item_class() -> &'static Class {
|
||||||
load_or_register_class("NSMenuItem", "CacaoMenuItem", |decl| unsafe {
|
load_or_register_class("NSMenuItem", "CacaoMenuItem", |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(BLOCK_PTR);
|
decl.add_ivar::<usize>(BLOCK_PTR);
|
||||||
|
|
||||||
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
|
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(_, _));
|
||||||
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
|
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(_, _, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::{Id, ShareId};
|
|
||||||
|
|
||||||
use crate::appkit::menu::item::MenuItem;
|
use crate::appkit::menu::item::MenuItem;
|
||||||
use crate::foundation::{id, NSInteger, NSString};
|
use crate::foundation::{id, NSInteger, NSString};
|
||||||
|
@ -12,7 +12,7 @@ use crate::foundation::{id, NSInteger, NSString};
|
||||||
/// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting
|
/// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting
|
||||||
/// them throughout the application lifecycle.
|
/// them throughout the application lifecycle.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Menu(pub Id<Object>);
|
pub struct Menu(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Menu {
|
impl Menu {
|
||||||
/// Creates a new `Menu` with the given title, and uses the passed items as submenu items.
|
/// Creates a new `Menu` with the given title, and uses the passed items as submenu items.
|
||||||
|
@ -27,16 +27,16 @@ impl Menu {
|
||||||
pub fn new(title: &str, items: Vec<MenuItem>) -> Self {
|
pub fn new(title: &str, items: Vec<MenuItem>) -> Self {
|
||||||
Menu(unsafe {
|
Menu(unsafe {
|
||||||
let cls = class!(NSMenu);
|
let cls = class!(NSMenu);
|
||||||
let alloc: id = msg_send![cls, alloc];
|
let alloc = msg_send_id![cls, alloc];
|
||||||
let title = NSString::new(title);
|
let title = NSString::new(title);
|
||||||
let menu: id = msg_send![alloc, initWithTitle:&*title];
|
let mut menu = msg_send_id![alloc, initWithTitle: &*title];
|
||||||
|
|
||||||
for item in items.into_iter() {
|
for item in items.into_iter() {
|
||||||
let objc = item.to_objc();
|
let objc = item.to_objc();
|
||||||
let _: () = msg_send![menu, addItem:&*objc];
|
let _: () = msg_send![&mut menu, addItem:&*objc];
|
||||||
}
|
}
|
||||||
|
|
||||||
Id::from_retained_ptr(menu)
|
menu
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Represents settings for printing items. Backed by an `NSDictionary` in Objective-C, this struct
|
//! Represents settings for printing items. Backed by an `NSDictionary` in Objective-C, this struct
|
||||||
//! aims to make it easier to query/process printing operations.
|
//! aims to make it easier to query/process printing operations.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ use crate::foundation::id;
|
||||||
/// application/user.
|
/// application/user.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PrintSettings {
|
pub struct PrintSettings {
|
||||||
pub inner: ShareId<Object>
|
pub inner: Id<Object, Shared>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrintSettings {
|
impl PrintSettings {
|
||||||
/// Internal method, constructs a wrapper around the backing `NSDictionary` print settings.
|
/// Internal method, constructs a wrapper around the backing `NSDictionary` print settings.
|
||||||
pub(crate) fn with_inner(inner: id) -> Self {
|
pub(crate) fn with_inner(inner: id) -> Self {
|
||||||
PrintSettings {
|
PrintSettings {
|
||||||
inner: unsafe { ShareId::from_ptr(inner) }
|
inner: unsafe { Id::retain(inner).unwrap() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Class, Object, Sel};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::control::Control;
|
use crate::control::Control;
|
||||||
|
@ -171,7 +171,7 @@ impl SegmentedControl {
|
||||||
pub fn set_tooltip_segment(&mut self, index: NSUInteger, tooltip: &str) {
|
pub fn set_tooltip_segment(&mut self, index: NSUInteger, tooltip: &str) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let converted = NSString::new(tooltip);
|
let converted = NSString::new(tooltip);
|
||||||
let _: () = msg_send![obj, setToolTip: converted forSegment: index];
|
let _: () = msg_send![obj, setToolTip: &*converted.objc, forSegment: index];
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ impl SegmentedControl {
|
||||||
/// best just to message pass or something.
|
/// best just to message pass or something.
|
||||||
pub fn set_action<F: Fn(i32) + Send + Sync + 'static>(&mut self, action: F) {
|
pub fn set_action<F: Fn(i32) + Send + Sync + 'static>(&mut self, action: F) {
|
||||||
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
||||||
let this = self.objc.get(|obj| unsafe { ShareId::from_ptr(msg_send![obj, self]) });
|
let this: Id<_, Shared> = self.objc.get(|obj| unsafe { msg_send_id![obj, self] });
|
||||||
let handler = TargetActionHandler::new(&*this, move |obj: *const Object| unsafe {
|
let handler = TargetActionHandler::new(&*this, move |obj: *const Object| unsafe {
|
||||||
let selected: i32 = msg_send![obj, selectedSegment];
|
let selected: i32 = msg_send![obj, selectedSegment];
|
||||||
action(selected)
|
action(selected)
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::rc::Id;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::appkit::toolbar::{ToolbarDelegate, TOOLBAR_PTR};
|
use crate::appkit::toolbar::{ToolbarDelegate, TOOLBAR_PTR};
|
||||||
use crate::foundation::{id, load_or_register_class, NSArray, NSString, BOOL};
|
use crate::foundation::{id, load_or_register_class, NSArray, NSString};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
|
||||||
/// Retrieves and passes the allowed item identifiers for this toolbar.
|
/// Retrieves and passes the allowed item identifiers for this toolbar.
|
||||||
|
@ -21,7 +22,7 @@ extern "C" fn allowed_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel
|
||||||
.collect::<Vec<id>>()
|
.collect::<Vec<id>>()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
identifiers.into()
|
Id::autorelease_return(identifiers.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves and passes the default item identifiers for this toolbar.
|
/// Retrieves and passes the default item identifiers for this toolbar.
|
||||||
|
@ -35,7 +36,7 @@ extern "C" fn default_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel
|
||||||
.collect::<Vec<id>>()
|
.collect::<Vec<id>>()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
identifiers.into()
|
Id::autorelease_return(identifiers.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves and passes the default item identifiers for this toolbar.
|
/// Retrieves and passes the default item identifiers for this toolbar.
|
||||||
|
@ -49,14 +50,14 @@ extern "C" fn selectable_item_identifiers<T: ToolbarDelegate>(this: &Object, _:
|
||||||
.collect::<Vec<id>>()
|
.collect::<Vec<id>>()
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
identifiers.into()
|
Id::autorelease_return(identifiers.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the controller, grabs whatever item is for this identifier, and returns what the
|
/// Loads the controller, grabs whatever item is for this identifier, and returns what the
|
||||||
/// Objective-C runtime needs.
|
/// Objective-C runtime needs.
|
||||||
extern "C" fn item_for_identifier<T: ToolbarDelegate>(this: &Object, _: Sel, _: id, identifier: id, _: BOOL) -> id {
|
extern "C" fn item_for_identifier<T: ToolbarDelegate>(this: &Object, _: Sel, _: id, identifier: id, _: Bool) -> id {
|
||||||
let toolbar = load::<T>(this, TOOLBAR_PTR);
|
let toolbar = load::<T>(this, TOOLBAR_PTR);
|
||||||
let identifier = NSString::from_retained(identifier);
|
let identifier = NSString::retain(identifier);
|
||||||
|
|
||||||
let item = toolbar.item_for(identifier.to_str());
|
let item = toolbar.item_for(identifier.to_str());
|
||||||
unsafe { msg_send![&*item.objc, self] }
|
unsafe { msg_send![&*item.objc, self] }
|
||||||
|
@ -65,7 +66,7 @@ extern "C" fn item_for_identifier<T: ToolbarDelegate>(this: &Object, _: Sel, _:
|
||||||
|
|
||||||
/// Registers a `NSToolbar` subclass, and configures it to hold some ivars for various things we need
|
/// Registers a `NSToolbar` subclass, and configures it to hold some ivars for various things we need
|
||||||
/// to store. We use it as our delegate as well, just to cut down on moving pieces.
|
/// to store. We use it as our delegate as well, just to cut down on moving pieces.
|
||||||
pub(crate) fn register_toolbar_class<T: ToolbarDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_toolbar_class<T: ToolbarDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSObject", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSObject", instance.subclass_name(), |decl| unsafe {
|
||||||
// For callbacks
|
// For callbacks
|
||||||
decl.add_ivar::<usize>(TOOLBAR_PTR);
|
decl.add_ivar::<usize>(TOOLBAR_PTR);
|
||||||
|
@ -73,19 +74,19 @@ pub(crate) fn register_toolbar_class<T: ToolbarDelegate>(instance: &T) -> *const
|
||||||
// Add callback methods
|
// Add callback methods
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(toolbarAllowedItemIdentifiers:),
|
sel!(toolbarAllowedItemIdentifiers:),
|
||||||
allowed_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
|
allowed_item_identifiers::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(toolbarDefaultItemIdentifiers:),
|
sel!(toolbarDefaultItemIdentifiers:),
|
||||||
default_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
|
default_item_identifiers::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(toolbarSelectableItemIdentifiers:),
|
sel!(toolbarSelectableItemIdentifiers:),
|
||||||
selectable_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
|
selectable_item_identifiers::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:),
|
sel!(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:),
|
||||||
item_for_identifier::<T> as extern "C" fn(&Object, _, _, _, _) -> id
|
item_for_identifier::<T> as extern "C" fn(_, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! Various types used for Toolbar configuration.
|
//! Various types used for Toolbar configuration.
|
||||||
|
|
||||||
|
use objc::rc::Id;
|
||||||
|
|
||||||
use crate::foundation::{id, NSString, NSUInteger};
|
use crate::foundation::{id, NSString, NSUInteger};
|
||||||
|
|
||||||
/// Represents the display mode(s) a Toolbar can render in.
|
/// Represents the display mode(s) a Toolbar can render in.
|
||||||
|
@ -95,7 +97,8 @@ impl ItemIdentifier {
|
||||||
pub(crate) fn to_nsstring(&self) -> id {
|
pub(crate) fn to_nsstring(&self) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self {
|
match self {
|
||||||
Self::Custom(s) => NSString::new(s).into(),
|
// FIXME: We shouldn't use autorelease here
|
||||||
|
Self::Custom(s) => Id::autorelease_return(NSString::new(s).objc),
|
||||||
Self::CloudSharing => NSToolbarCloudSharingItemIdentifier,
|
Self::CloudSharing => NSToolbarCloudSharingItemIdentifier,
|
||||||
Self::FlexibleSpace => NSToolbarFlexibleSpaceItemIdentifier,
|
Self::FlexibleSpace => NSToolbarFlexibleSpaceItemIdentifier,
|
||||||
Self::Print => NSToolbarPrintItemIdentifier,
|
Self::Print => NSToolbarPrintItemIdentifier,
|
||||||
|
@ -106,7 +109,10 @@ impl ItemIdentifier {
|
||||||
|
|
||||||
// This ensures that the framework compiles and runs on 10.15.7 and lower; it will
|
// This ensures that the framework compiles and runs on 10.15.7 and lower; it will
|
||||||
// not actually work on anything except 11.0+. Use a runtime check to be safe.
|
// not actually work on anything except 11.0+. Use a runtime check to be safe.
|
||||||
Self::SidebarTracker => NSString::no_copy("NSToolbarSidebarTrackingSeparatorItemIdentifier").into()
|
// FIXME: We shouldn't use autorelease here
|
||||||
|
Self::SidebarTracker => {
|
||||||
|
Id::autorelease_return(NSString::no_copy("NSToolbarSidebarTrackingSeparatorItemIdentifier").objc)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
use core_graphics::geometry::CGSize;
|
use core_graphics::geometry::CGSize;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::{Id, ShareId};
|
|
||||||
|
|
||||||
use crate::appkit::segmentedcontrol::SegmentedControl;
|
use crate::appkit::segmentedcontrol::SegmentedControl;
|
||||||
use crate::button::{BezelStyle, Button};
|
use crate::button::{BezelStyle, Button};
|
||||||
|
@ -20,7 +20,7 @@ use crate::invoker::TargetActionHandler;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ToolbarItem {
|
pub struct ToolbarItem {
|
||||||
pub identifier: String,
|
pub identifier: String,
|
||||||
pub objc: Id<Object>,
|
pub objc: Id<Object, Owned>,
|
||||||
pub button: Option<Button>,
|
pub button: Option<Button>,
|
||||||
pub segmented_control: Option<SegmentedControl>,
|
pub segmented_control: Option<SegmentedControl>,
|
||||||
pub image: Option<Image>,
|
pub image: Option<Image>,
|
||||||
|
@ -34,10 +34,9 @@ impl ToolbarItem {
|
||||||
let identifier = identifier.into();
|
let identifier = identifier.into();
|
||||||
|
|
||||||
let objc = unsafe {
|
let objc = unsafe {
|
||||||
let identifr = NSString::new(&identifier);
|
let identifer = NSString::new(&identifier);
|
||||||
let alloc: id = msg_send![class!(NSToolbarItem), alloc];
|
let alloc = msg_send_id![class!(NSToolbarItem), alloc];
|
||||||
let item: id = msg_send![alloc, initWithItemIdentifier: identifr];
|
msg_send_id![alloc, initWithItemIdentifier: &*identifer]
|
||||||
Id::from_ptr(item)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
|
@ -50,17 +49,6 @@ impl ToolbarItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn wrap(item: id) -> Self {
|
|
||||||
ToolbarItem {
|
|
||||||
identifier: "".to_string(),
|
|
||||||
objc: unsafe { Id::from_retained_ptr(item) },
|
|
||||||
button: None,
|
|
||||||
segmented_control: None,
|
|
||||||
image: None,
|
|
||||||
handler: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the title for this item.
|
/// Sets the title for this item.
|
||||||
pub fn set_title(&mut self, title: &str) {
|
pub fn set_title(&mut self, title: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSString, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, NSString, NSUInteger, NO, YES};
|
||||||
|
|
||||||
|
@ -32,10 +32,10 @@ pub struct Toolbar<T = ()> {
|
||||||
pub identifier: String,
|
pub identifier: String,
|
||||||
|
|
||||||
/// The Objective-C runtime toolbar.
|
/// The Objective-C runtime toolbar.
|
||||||
pub objc: ShareId<Object>,
|
pub objc: Id<Object, Shared>,
|
||||||
|
|
||||||
/// A pointer to the underlying delegate.
|
/// A pointer to the underlying delegate.
|
||||||
pub objc_delegate: ShareId<Object>,
|
pub objc_delegate: Id<Object, Shared>,
|
||||||
|
|
||||||
/// The user supplied delegate.
|
/// The user supplied delegate.
|
||||||
pub delegate: Option<Box<T>>
|
pub delegate: Option<Box<T>>
|
||||||
|
@ -53,16 +53,18 @@ where
|
||||||
let mut delegate = Box::new(delegate);
|
let mut delegate = Box::new(delegate);
|
||||||
|
|
||||||
let (objc, objc_delegate) = unsafe {
|
let (objc, objc_delegate) = unsafe {
|
||||||
let alloc: id = msg_send![class!(NSToolbar), alloc];
|
let alloc = msg_send_id![class!(NSToolbar), alloc];
|
||||||
let identifier = NSString::new(&identifier);
|
let identifier = NSString::new(&identifier);
|
||||||
let toolbar: id = msg_send![alloc, initWithIdentifier: identifier];
|
let mut toolbar: Id<Object, Owned> = msg_send_id![alloc, initWithIdentifier: &*identifier];
|
||||||
let objc_delegate: id = msg_send![cls, new]; //WithIdentifier:identifier];
|
let mut objc_delegate: Id<Object, Owned> = msg_send_id![cls, new]; //WithIdentifier:identifier];
|
||||||
|
|
||||||
let ptr: *const T = &*delegate;
|
let ptr: *const T = &*delegate;
|
||||||
(&mut *objc_delegate).set_ivar(TOOLBAR_PTR, ptr as usize);
|
objc_delegate.set_ivar(TOOLBAR_PTR, ptr as usize);
|
||||||
let _: () = msg_send![toolbar, setDelegate: objc_delegate];
|
|
||||||
|
|
||||||
(ShareId::from_ptr(toolbar), ShareId::from_ptr(objc_delegate))
|
let objc_delegate: Id<Object, Shared> = Id::into_shared(objc_delegate);
|
||||||
|
let _: () = msg_send![&mut toolbar, setDelegate: &*objc_delegate];
|
||||||
|
|
||||||
|
(Id::into_shared(toolbar), objc_delegate)
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ret = &mut delegate.did_load(Toolbar {
|
let _ret = &mut delegate.did_load(Toolbar {
|
||||||
|
|
|
@ -6,22 +6,19 @@ use std::sync::Once;
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc::{class, sel, sel_impl};
|
use objc::{class, sel};
|
||||||
|
|
||||||
use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
|
use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
|
||||||
use crate::foundation::{id, load_or_register_class, NSUInteger, BOOL, NO, YES};
|
use crate::foundation::{id, load_or_register_class, NSUInteger};
|
||||||
use crate::utils::{load, CGSize};
|
use crate::utils::{load, CGSize};
|
||||||
|
|
||||||
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
|
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
|
||||||
/// Good place to clean up memory and what not.
|
/// Good place to clean up memory and what not.
|
||||||
extern "C" fn should_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn should_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) -> Bool {
|
||||||
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
|
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
|
||||||
|
|
||||||
match window.should_close() {
|
Bool::new(window.should_close())
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
|
/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event.
|
||||||
|
@ -227,117 +224,99 @@ extern "C" fn cancel<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
|
||||||
|
|
||||||
/// Injects an `NSWindowDelegate` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSWindowDelegate` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_window_class_with_delegate<T: WindowDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_window_class_with_delegate<T: WindowDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSWindow", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSWindow", instance.subclass_name(), |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
||||||
|
|
||||||
// NSWindowDelegate methods
|
// NSWindowDelegate methods
|
||||||
decl.add_method(
|
decl.add_method(sel!(windowShouldClose:), should_close::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(windowShouldClose:),
|
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern "C" fn(_, _, _));
|
||||||
should_close::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
|
||||||
);
|
|
||||||
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern "C" fn(&Object, _, _));
|
|
||||||
|
|
||||||
// Sizing
|
// Sizing
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillResize:toSize:),
|
sel!(windowWillResize:toSize:),
|
||||||
will_resize::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize
|
will_resize::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(windowDidResize:), did_resize::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidResize:), did_resize::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillStartLiveResize:),
|
sel!(windowWillStartLiveResize:),
|
||||||
will_start_live_resize::<T> as extern "C" fn(&Object, _, _)
|
will_start_live_resize::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidEndLiveResize:),
|
sel!(windowDidEndLiveResize:),
|
||||||
did_end_live_resize::<T> as extern "C" fn(&Object, _, _)
|
did_end_live_resize::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Minimizing
|
// Minimizing
|
||||||
decl.add_method(
|
decl.add_method(sel!(windowWillMiniaturize:), will_miniaturize::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(windowWillMiniaturize:),
|
decl.add_method(sel!(windowDidMiniaturize:), did_miniaturize::<T> as extern "C" fn(_, _, _));
|
||||||
will_miniaturize::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(windowDidMiniaturize:),
|
|
||||||
did_miniaturize::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidDeminiaturize:),
|
sel!(windowDidDeminiaturize:),
|
||||||
did_deminiaturize::<T> as extern "C" fn(&Object, _, _)
|
did_deminiaturize::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Full Screen
|
// Full Screen
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(window:willUseFullScreenContentSize:),
|
sel!(window:willUseFullScreenContentSize:),
|
||||||
content_size_for_full_screen::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize
|
content_size_for_full_screen::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(window:willUseFullScreenPresentationOptions:),
|
sel!(window:willUseFullScreenPresentationOptions:),
|
||||||
options_for_full_screen::<T> as extern "C" fn(&Object, _, _, NSUInteger) -> NSUInteger
|
options_for_full_screen::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillEnterFullScreen:),
|
sel!(windowWillEnterFullScreen:),
|
||||||
will_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
|
will_enter_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidEnterFullScreen:),
|
sel!(windowDidEnterFullScreen:),
|
||||||
did_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
|
did_enter_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowWillExitFullScreen:),
|
sel!(windowWillExitFullScreen:),
|
||||||
will_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
|
will_exit_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidExitFullScreen:),
|
sel!(windowDidExitFullScreen:),
|
||||||
did_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
|
did_exit_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidFailToEnterFullScreen:),
|
sel!(windowDidFailToEnterFullScreen:),
|
||||||
did_fail_to_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
|
did_fail_to_enter_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidFailToExitFullScreen:),
|
sel!(windowDidFailToExitFullScreen:),
|
||||||
did_fail_to_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
|
did_fail_to_exit_full_screen::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Key status
|
// Key status
|
||||||
decl.add_method(sel!(windowDidBecomeKey:), did_become_key::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidBecomeKey:), did_become_key::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(windowDidResignKey:), did_resign_key::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidResignKey:), did_resign_key::<T> as extern "C" fn(_, _, _));
|
||||||
|
|
||||||
// Main status
|
// Main status
|
||||||
decl.add_method(
|
decl.add_method(sel!(windowDidBecomeMain:), did_become_main::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(windowDidBecomeMain:),
|
decl.add_method(sel!(windowDidResignMain:), did_resign_main::<T> as extern "C" fn(_, _, _));
|
||||||
did_become_main::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(windowDidResignMain:),
|
|
||||||
did_resign_main::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Moving Windows
|
// Moving Windows
|
||||||
decl.add_method(sel!(windowWillMove:), will_move::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowWillMove:), will_move::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(windowDidMove:), did_move::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidMove:), did_move::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(sel!(windowDidChangeScreen:), did_change_screen::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(windowDidChangeScreen:),
|
|
||||||
did_change_screen::<T> as extern "C" fn(&Object, _, _)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidChangeScreenProfile:),
|
sel!(windowDidChangeScreenProfile:),
|
||||||
did_change_screen_profile::<T> as extern "C" fn(&Object, _, _)
|
did_change_screen_profile::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidChangeBackingProperties:),
|
sel!(windowDidChangeBackingProperties:),
|
||||||
did_change_backing_properties::<T> as extern "C" fn(&Object, _, _)
|
did_change_backing_properties::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Random
|
// Random
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(windowDidChangeOcclusionState:),
|
sel!(windowDidChangeOcclusionState:),
|
||||||
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
|
did_change_occlusion_state::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(windowDidExpose:), did_expose::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidExpose:), did_expose::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(windowDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(windowDidUpdate:), did_update::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(sel!(cancelOperation:), cancel::<T> as extern "C" fn(&Object, _, _));
|
decl.add_method(sel!(cancelOperation:), cancel::<T> as extern "C" fn(_, _, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::foundation::load_or_register_class;
|
||||||
|
|
||||||
/// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class {
|
pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> &'static Class {
|
||||||
load_or_register_class("NSWindowController", "RSTWindowController", |decl| unsafe {
|
load_or_register_class("NSWindowController", "RSTWindowController", |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::appkit::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
|
use crate::appkit::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
|
||||||
use crate::foundation::{id, nil};
|
use crate::foundation::{id, nil};
|
||||||
|
@ -45,7 +45,7 @@ use class::register_window_controller_class;
|
||||||
/// provides some extra lifecycle methods.
|
/// provides some extra lifecycle methods.
|
||||||
pub struct WindowController<T> {
|
pub struct WindowController<T> {
|
||||||
/// A handler to the underlying `NSWindowController`.
|
/// A handler to the underlying `NSWindowController`.
|
||||||
pub objc: Id<Object>,
|
pub objc: Id<Object, Owned>,
|
||||||
|
|
||||||
/// The underlying `Window` that this controller wraps.
|
/// The underlying `Window` that this controller wraps.
|
||||||
pub window: Window<T>
|
pub window: Window<T>
|
||||||
|
@ -62,15 +62,15 @@ where
|
||||||
|
|
||||||
let objc = unsafe {
|
let objc = unsafe {
|
||||||
let window_controller_class = register_window_controller_class::<T>();
|
let window_controller_class = register_window_controller_class::<T>();
|
||||||
let controller_alloc: id = msg_send![window_controller_class, alloc];
|
let controller_alloc = msg_send_id![window_controller_class, alloc];
|
||||||
let controller: id = msg_send![controller_alloc, initWithWindow:&*window.objc];
|
let mut controller: Id<Object, Owned> = msg_send_id![controller_alloc, initWithWindow: &*window.objc];
|
||||||
|
|
||||||
if let Some(delegate) = &window.delegate {
|
if let Some(delegate) = &window.delegate {
|
||||||
let ptr: *const T = &**delegate;
|
let ptr: *const T = &**delegate;
|
||||||
(&mut *controller).set_ivar(WINDOW_DELEGATE_PTR, ptr as usize);
|
controller.set_ivar(WINDOW_DELEGATE_PTR, ptr as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id::from_ptr(controller)
|
controller
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowController { objc, window }
|
WindowController { objc, window }
|
||||||
|
|
|
@ -13,9 +13,9 @@ use block::ConcreteBlock;
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
use core_graphics::geometry::{CGRect, CGSize};
|
use core_graphics::geometry::{CGRect, CGSize};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::appkit::toolbar::{Toolbar, ToolbarDelegate};
|
use crate::appkit::toolbar::{Toolbar, ToolbarDelegate};
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
|
@ -47,7 +47,7 @@ pub(crate) static WINDOW_DELEGATE_PTR: &str = "rstWindowDelegate";
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Window<T = ()> {
|
pub struct Window<T = ()> {
|
||||||
/// Represents an `NS/UIWindow` in the Objective-C runtime.
|
/// Represents an `NS/UIWindow` in the Objective-C runtime.
|
||||||
pub objc: ShareId<Object>,
|
pub objc: Id<Object, Shared>,
|
||||||
|
|
||||||
/// A delegate for this window.
|
/// A delegate for this window.
|
||||||
pub delegate: Option<Box<T>>
|
pub delegate: Option<Box<T>>
|
||||||
|
@ -72,40 +72,38 @@ impl Window {
|
||||||
// apps that would use this toolkit wouldn't be tab-oriented...
|
// apps that would use this toolkit wouldn't be tab-oriented...
|
||||||
let _: () = msg_send![class!(NSWindow), setAllowsAutomaticWindowTabbing: NO];
|
let _: () = msg_send![class!(NSWindow), setAllowsAutomaticWindowTabbing: NO];
|
||||||
|
|
||||||
let alloc: id = msg_send![class!(NSWindow), alloc];
|
|
||||||
|
|
||||||
// Other types of backing (Retained/NonRetained) are archaic, dating back to the
|
// Other types of backing (Retained/NonRetained) are archaic, dating back to the
|
||||||
// NeXTSTEP era, and are outright deprecated... so we don't allow setting them.
|
// NeXTSTEP era, and are outright deprecated... so we don't allow setting them.
|
||||||
let buffered: NSUInteger = 2;
|
let buffered: NSUInteger = 2;
|
||||||
let dimensions: CGRect = config.initial_dimensions.into();
|
let dimensions: CGRect = config.initial_dimensions.into();
|
||||||
let window: id = msg_send![alloc, initWithContentRect:dimensions
|
let window: Id<_, _> = msg_send_id![
|
||||||
styleMask:config.style
|
msg_send_id![class!(NSWindow), alloc],
|
||||||
backing:buffered
|
initWithContentRect: dimensions,
|
||||||
defer:match config.defer {
|
styleMask: config.style,
|
||||||
|
backing: buffered,
|
||||||
|
defer: match config.defer {
|
||||||
true => YES,
|
true => YES,
|
||||||
false => NO
|
false => NO
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let _: () = msg_send![window, autorelease];
|
|
||||||
|
|
||||||
// This is very important! NSWindow is an old class and has some behavior that we need
|
// This is very important! NSWindow is an old class and has some behavior that we need
|
||||||
// to disable, like... this. If we don't set this, we'll segfault entirely because the
|
// to disable, like... this. If we don't set this, we'll segfault entirely because the
|
||||||
// Objective-C runtime gets out of sync by releasing the window out from underneath of
|
// Objective-C runtime gets out of sync by releasing the window out from underneath of
|
||||||
// us.
|
// us.
|
||||||
let _: () = msg_send![window, setReleasedWhenClosed: NO];
|
let _: () = msg_send![&*window, setReleasedWhenClosed: NO];
|
||||||
|
|
||||||
let _: () = msg_send![window, setRestorable: NO];
|
let _: () = msg_send![&*window, setRestorable: NO];
|
||||||
|
|
||||||
// This doesn't exist prior to Big Sur, but is important to support for Big Sur.
|
// This doesn't exist prior to Big Sur, but is important to support for Big Sur.
|
||||||
//
|
//
|
||||||
// Why this isn't a setting on the Toolbar itself I'll never know.
|
// Why this isn't a setting on the Toolbar itself I'll never know.
|
||||||
if os::is_minimum_version(11) {
|
if os::is_minimum_version(11) {
|
||||||
let toolbar_style: NSUInteger = config.toolbar_style.into();
|
let toolbar_style: NSUInteger = config.toolbar_style.into();
|
||||||
let _: () = msg_send![window, setToolbarStyle: toolbar_style];
|
let _: () = msg_send![&*window, setToolbarStyle: toolbar_style];
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareId::from_ptr(window)
|
window
|
||||||
};
|
};
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
|
@ -116,7 +114,7 @@ impl Window {
|
||||||
|
|
||||||
pub(crate) unsafe fn existing(window: *mut Object) -> Window {
|
pub(crate) unsafe fn existing(window: *mut Object) -> Window {
|
||||||
Window {
|
Window {
|
||||||
objc: ShareId::from_ptr(window),
|
objc: Id::retain(window).unwrap(),
|
||||||
delegate: None
|
delegate: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,51 +132,49 @@ where
|
||||||
let class = register_window_class_with_delegate::<T>(&delegate);
|
let class = register_window_class_with_delegate::<T>(&delegate);
|
||||||
let mut delegate = Box::new(delegate);
|
let mut delegate = Box::new(delegate);
|
||||||
|
|
||||||
let objc = unsafe {
|
let objc: Id<Object, Shared> = unsafe {
|
||||||
// This behavior might make sense to keep as default (YES), but I think the majority of
|
// This behavior might make sense to keep as default (YES), but I think the majority of
|
||||||
// apps that would use this toolkit wouldn't be tab-oriented...
|
// apps that would use this toolkit wouldn't be tab-oriented...
|
||||||
let _: () = msg_send![class!(NSWindow), setAllowsAutomaticWindowTabbing: NO];
|
let _: () = msg_send![class!(NSWindow), setAllowsAutomaticWindowTabbing: NO];
|
||||||
|
|
||||||
let alloc: id = msg_send![class, alloc];
|
|
||||||
|
|
||||||
// Other types of backing (Retained/NonRetained) are archaic, dating back to the
|
// Other types of backing (Retained/NonRetained) are archaic, dating back to the
|
||||||
// NeXTSTEP era, and are outright deprecated... so we don't allow setting them.
|
// NeXTSTEP era, and are outright deprecated... so we don't allow setting them.
|
||||||
let buffered: NSUInteger = 2;
|
let buffered: NSUInteger = 2;
|
||||||
let dimensions: CGRect = config.initial_dimensions.into();
|
let dimensions: CGRect = config.initial_dimensions.into();
|
||||||
let window: id = msg_send![alloc, initWithContentRect:dimensions
|
let mut window: Id<Object, Owned> = msg_send_id![
|
||||||
styleMask:config.style
|
msg_send_id![class, alloc],
|
||||||
backing:buffered
|
initWithContentRect: dimensions,
|
||||||
defer:match config.defer {
|
styleMask: config.style,
|
||||||
|
backing: buffered,
|
||||||
|
defer: match config.defer {
|
||||||
true => YES,
|
true => YES,
|
||||||
false => NO
|
false => NO
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let delegate_ptr: *const T = &*delegate;
|
let delegate_ptr: *const T = &*delegate;
|
||||||
(&mut *window).set_ivar(WINDOW_DELEGATE_PTR, delegate_ptr as usize);
|
window.set_ivar(WINDOW_DELEGATE_PTR, delegate_ptr as usize);
|
||||||
|
|
||||||
let _: () = msg_send![window, autorelease];
|
|
||||||
|
|
||||||
// This is very important! NSWindow is an old class and has some behavior that we need
|
// This is very important! NSWindow is an old class and has some behavior that we need
|
||||||
// to disable, like... this. If we don't set this, we'll segfault entirely because the
|
// to disable, like... this. If we don't set this, we'll segfault entirely because the
|
||||||
// Objective-C runtime gets out of sync by releasing the window out from underneath of
|
// Objective-C runtime gets out of sync by releasing the window out from underneath of
|
||||||
// us.
|
// us.
|
||||||
let _: () = msg_send![window, setReleasedWhenClosed: NO];
|
let _: () = msg_send![&*window, setReleasedWhenClosed: NO];
|
||||||
|
|
||||||
// We set the window to be its own delegate - this is cleaned up inside `Drop`.
|
// We set the window to be its own delegate - this is cleaned up inside `Drop`.
|
||||||
let _: () = msg_send![window, setDelegate: window];
|
let _: () = msg_send![&*window, setDelegate: &*window];
|
||||||
|
|
||||||
let _: () = msg_send![window, setRestorable: NO];
|
let _: () = msg_send![&*window, setRestorable: NO];
|
||||||
|
|
||||||
// This doesn't exist prior to Big Sur, but is important to support for Big Sur.
|
// This doesn't exist prior to Big Sur, but is important to support for Big Sur.
|
||||||
//
|
//
|
||||||
// Why this isn't a setting on the Toolbar itself I'll never know.
|
// Why this isn't a setting on the Toolbar itself I'll never know.
|
||||||
if os::is_minimum_version(11) {
|
if os::is_minimum_version(11) {
|
||||||
let toolbar_style: NSUInteger = config.toolbar_style.into();
|
let toolbar_style: NSUInteger = config.toolbar_style.into();
|
||||||
let _: () = msg_send![window, setToolbarStyle: toolbar_style];
|
let _: () = msg_send![&*window, setToolbarStyle: toolbar_style];
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareId::from_ptr(window)
|
window.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -201,7 +197,7 @@ impl<T> Window<T> {
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let title = NSString::new(title);
|
let title = NSString::new(title);
|
||||||
let _: () = msg_send![&*self.objc, setTitle: title];
|
let _: () = msg_send![&*self.objc, setTitle: &*title];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +212,7 @@ impl<T> Window<T> {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let subtitle = NSString::new(subtitle);
|
let subtitle = NSString::new(subtitle);
|
||||||
let _: () = msg_send![&*self.objc, setSubtitle: subtitle];
|
let _: () = msg_send![&*self.objc, setSubtitle: &*subtitle];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +248,7 @@ impl<T> Window<T> {
|
||||||
pub fn set_autosave_name(&self, name: &str) {
|
pub fn set_autosave_name(&self, name: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let autosave = NSString::new(name);
|
let autosave = NSString::new(name);
|
||||||
let _: () = msg_send![&*self.objc, setFrameAutosaveName: autosave];
|
let _: () = msg_send![&*self.objc, setFrameAutosaveName: &*autosave];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,11 +292,8 @@ impl<T> Window<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used for setting a toolbar on this window.
|
/// Used for setting a toolbar on this window.
|
||||||
pub fn toolbar(&self) -> ShareId<Object> {
|
pub fn toolbar(&self) -> Id<Object, Shared> {
|
||||||
unsafe {
|
unsafe { msg_send_id![&self.objc, toolbar] }
|
||||||
let o: *mut Object = msg_send![&*self.objc, toolbar];
|
|
||||||
ShareId::from_ptr(o)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggles whether the toolbar is shown for this window. Has no effect if no toolbar exists on
|
/// Toggles whether the toolbar is shown for this window. Has no effect if no toolbar exists on
|
||||||
|
@ -514,7 +507,7 @@ impl<T> Window<T> {
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.objc, beginSheet:&*window.objc completionHandler:block];
|
let _: () = msg_send![&*self.objc, beginSheet: &*window.objc, completionHandler: &*block];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,9 @@
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl, Encode, Encoding, EncodeArguments, Message};
|
use objc::ffi;
|
||||||
use objc::runtime::{Class, Sel, Method, Object, Imp};
|
use objc::runtime::{Class, Imp, Object, Sel};
|
||||||
use objc::runtime::{
|
use objc::{class, msg_send, sel, Encode, EncodeArguments, Encoding, Message};
|
||||||
objc_getClass,
|
|
||||||
class_addMethod,
|
|
||||||
class_getInstanceMethod,
|
|
||||||
method_exchangeImplementations
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, BOOL, YES, NSString};
|
use crate::foundation::{id, nil, BOOL, YES, NSString};
|
||||||
|
|
||||||
|
@ -73,24 +68,27 @@ extern "C" fn get_bundle_id(this: &Object, s: Sel, v: id) -> id {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn swizzle_bundle_id<F>(bundle_id: &str, func: F) where F: MethodImplementation<Callee=Object> {
|
unsafe fn swizzle_bundle_id<F>(bundle_id: &str, func: F)
|
||||||
|
where
|
||||||
|
F: MethodImplementation<Callee = Object>,
|
||||||
|
{
|
||||||
let name = CString::new("NSBundle").unwrap();
|
let name = CString::new("NSBundle").unwrap();
|
||||||
let cls = objc_getClass(name.as_ptr());
|
let cls = ffi::objc_getClass(name.as_ptr());
|
||||||
|
|
||||||
// let mut cls = class!(NSBundle) as *mut Class;
|
// let mut cls = class!(NSBundle) as *mut Class;
|
||||||
// Class::get("NSBundle").unwrap();
|
// Class::get("NSBundle").unwrap();
|
||||||
// let types = format!("{}{}{}", Encoding::String, <*mut Object>::ENCODING, Sel::ENCODING);
|
// let types = format!("{}{}{}", Encoding::String, <*mut Object>::ENCODING, Sel::ENCODING);
|
||||||
|
|
||||||
let added = class_addMethod(
|
let added = ffi::class_addMethod(
|
||||||
cls as *mut Class,
|
cls as *mut ffi::objc_class,
|
||||||
sel!(__bundleIdentifier),
|
sel!(__bundleIdentifier).as_ptr(),
|
||||||
func.imp(),
|
func.imp(),
|
||||||
CString::new("*@:").unwrap().as_ptr()
|
CString::new("*@:").unwrap().as_ptr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let method1 = class_getInstanceMethod(cls, sel!(bundleIdentifier)) as *mut Method;
|
let method1 = ffi::class_getInstanceMethod(cls, sel!(bundleIdentifier).as_ptr()) as *mut ffi::objc_method;
|
||||||
let method2 = class_getInstanceMethod(cls, sel!(__bundleIdentifier)) as *mut Method;
|
let method2 = ffi::class_getInstanceMethod(cls, sel!(__bundleIdentifier).as_ptr()) as *mut ffi::objc_method;
|
||||||
method_exchangeImplementations(method1, method2);
|
ffi::method_exchangeImplementations(method1, method2);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_bundle_id(bundle_id: &str) {
|
pub fn set_bundle_id(bundle_id: &str) {
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
//! my_view.add_subview(&button);
|
//! my_view.add_subview(&button);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
pub use enums::*;
|
pub use enums::*;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ impl Button {
|
||||||
/// best just to message pass or something.
|
/// best just to message pass or something.
|
||||||
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
||||||
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
||||||
let this = self.objc.get(|obj| unsafe { ShareId::from_ptr(msg_send![obj, self]) });
|
let this: Id<Object, Shared> = self.objc.get(|obj| unsafe { msg_send_id![obj, self] });
|
||||||
let handler = TargetActionHandler::new(&*this, action);
|
let handler = TargetActionHandler::new(&*this, action);
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
}
|
}
|
||||||
|
@ -352,7 +352,7 @@ impl Drop for Button {
|
||||||
|
|
||||||
/// Registers an `NSButton` subclass, and configures it to hold some ivars
|
/// Registers an `NSButton` subclass, and configures it to hold some ivars
|
||||||
/// for various things we need to store.
|
/// for various things we need to store.
|
||||||
fn register_class() -> *const Class {
|
fn register_class() -> &'static Class {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
let super_class = "NSButton";
|
let super_class = "NSButton";
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This module includes wrappers for `CKShare` and `CKShareMetaData`.
|
//! This module includes wrappers for `CKShare` and `CKShareMetaData`.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
|
@ -9,14 +9,14 @@ use crate::foundation::id;
|
||||||
/// to, say, handle accepting an invite for a share.
|
/// to, say, handle accepting an invite for a share.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CKShareMetaData {
|
pub struct CKShareMetaData {
|
||||||
pub inner: ShareId<Object>
|
pub inner: Id<Object, Shared>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CKShareMetaData {
|
impl CKShareMetaData {
|
||||||
/// Internal method for wrapping a system-provided `CKShareMetaData` object.
|
/// Internal method for wrapping a system-provided `CKShareMetaData` object.
|
||||||
pub(crate) fn with_inner(object: id) -> Self {
|
pub(crate) fn with_inner(object: id) -> Self {
|
||||||
CKShareMetaData {
|
CKShareMetaData {
|
||||||
inner: unsafe { ShareId::from_ptr(object) }
|
inner: unsafe { Id::retain(object).unwrap() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Class, Object, Sel};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class, nil, NSArray, NSInteger};
|
use crate::foundation::{id, load_or_register_class, nil, NSArray, NSInteger};
|
||||||
use crate::utils::os;
|
use crate::utils::os;
|
||||||
|
@ -253,95 +253,68 @@ extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger)
|
||||||
unsafe { msg_send![color, colorWithSystemEffect: effect] }
|
unsafe { msg_send![color, colorWithSystemEffect: effect] }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_class() -> *const Class {
|
pub(crate) fn register_class() -> &'static Class {
|
||||||
load_or_register_class("NSColor", "CacaoDynamicColor", |decl| unsafe {
|
load_or_register_class("NSColor", "CacaoDynamicColor", |decl| unsafe {
|
||||||
// These methods all need to be forwarded, so let's hook them up.
|
// These methods all need to be forwarded, so let's hook them up.
|
||||||
decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id);
|
decl.add_method(sel!(colorSpace), color_space as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(colorUsingColorSpace:),
|
sel!(colorUsingColorSpace:),
|
||||||
color_using_color_space as extern "C" fn(&Object, _, id) -> id
|
color_using_color_space as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id);
|
decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(colorUsingColorSpaceName:),
|
sel!(colorUsingColorSpaceName:),
|
||||||
color_using_color_space_name as extern "C" fn(&Object, _, id) -> id
|
color_using_color_space_name as extern "C" fn(_, _, _) -> _
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(numberOfComponents),
|
|
||||||
number_of_components as extern "C" fn(&Object, _) -> NSInteger
|
|
||||||
);
|
);
|
||||||
|
decl.add_method(sel!(numberOfComponents), number_of_components as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
decl.add_method(sel!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat));
|
decl.add_method(sel!(getComponents:), get_components as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(sel!(getRed:green:blue:alpha:), get_rgba as extern "C" fn(_, _, _, _, _, _));
|
||||||
sel!(getRed:green:blue:alpha:),
|
decl.add_method(sel!(redComponent), red_component as extern "C" fn(_, _) -> _);
|
||||||
get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
decl.add_method(sel!(greenComponent), green_component as extern "C" fn(_, _) -> _);
|
||||||
);
|
decl.add_method(sel!(blueComponent), blue_component as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(sel!(redComponent), red_component as extern "C" fn(&Object, _) -> CGFloat);
|
|
||||||
decl.add_method(sel!(greenComponent), green_component as extern "C" fn(&Object, _) -> CGFloat);
|
|
||||||
decl.add_method(sel!(blueComponent), blue_component as extern "C" fn(&Object, _) -> CGFloat);
|
|
||||||
|
|
||||||
decl.add_method(sel!(hueComponent), hue_component as extern "C" fn(&Object, _) -> CGFloat);
|
decl.add_method(sel!(hueComponent), hue_component as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(
|
decl.add_method(sel!(saturationComponent), saturation_component as extern "C" fn(_, _) -> _);
|
||||||
sel!(saturationComponent),
|
decl.add_method(sel!(brightnessComponent), brightness_component as extern "C" fn(_, _) -> _);
|
||||||
saturation_component as extern "C" fn(&Object, _) -> CGFloat
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(brightnessComponent),
|
|
||||||
brightness_component as extern "C" fn(&Object, _) -> CGFloat
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(getHue:saturation:brightness:alpha:),
|
sel!(getHue:saturation:brightness:alpha:),
|
||||||
get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
get_hsba as extern "C" fn(_, _, _, _, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat);
|
decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(
|
decl.add_method(sel!(getWhite:alpha:), get_white as extern "C" fn(_, _, _, _));
|
||||||
sel!(getWhite:alpha:),
|
|
||||||
get_white as extern "C" fn(&Object, _, CGFloat, CGFloat)
|
|
||||||
);
|
|
||||||
|
|
||||||
decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat);
|
decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(
|
decl.add_method(sel!(magentaComponent), magenta_component as extern "C" fn(_, _) -> _);
|
||||||
sel!(magentaComponent),
|
decl.add_method(sel!(yellowComponent), yellow_component as extern "C" fn(_, _) -> _);
|
||||||
magenta_component as extern "C" fn(&Object, _) -> CGFloat
|
decl.add_method(sel!(blackComponent), black_component as extern "C" fn(_, _) -> _);
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(yellowComponent),
|
|
||||||
yellow_component as extern "C" fn(&Object, _) -> CGFloat
|
|
||||||
);
|
|
||||||
decl.add_method(sel!(blackComponent), black_component as extern "C" fn(&Object, _) -> CGFloat);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(getCyan:magenta:yellow:black:alpha:),
|
sel!(getCyan:magenta:yellow:black:alpha:),
|
||||||
get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat)
|
get_cmyk as extern "C" fn(_, _, _, _, _, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(&Object, _) -> CGFloat);
|
decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id);
|
decl.add_method(sel!(CGColor), cg_color as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _));
|
decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(_, _));
|
||||||
decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _));
|
decl.add_method(sel!(setFill), set_fill as extern "C" fn(_, _));
|
||||||
decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _));
|
decl.add_method(sel!(set), call_set as extern "C" fn(_, _));
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(sel!(highlightWithLevel:), highlight_with_level as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(highlightWithLevel:),
|
decl.add_method(sel!(shadowWithLevel:), shadow_with_level as extern "C" fn(_, _, _) -> _);
|
||||||
highlight_with_level as extern "C" fn(&Object, _, CGFloat) -> id
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(shadowWithLevel:),
|
|
||||||
shadow_with_level as extern "C" fn(&Object, _, CGFloat) -> id
|
|
||||||
);
|
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(colorWithAlphaComponent:),
|
sel!(colorWithAlphaComponent:),
|
||||||
color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id
|
color_with_alpha_component as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(blendedColorWithFraction:ofColor:),
|
sel!(blendedColorWithFraction:ofColor:),
|
||||||
blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id
|
blended_color as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(colorWithSystemEffect:),
|
sel!(colorWithSystemEffect:),
|
||||||
color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id
|
color_with_system_effect as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST);
|
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST);
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
/// @TODO: bundle iOS/tvOS support.
|
/// @TODO: bundle iOS/tvOS support.
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
use core_graphics::color::CGColor;
|
use core_graphics::color::CGColor;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::utils::os;
|
use crate::utils::os;
|
||||||
|
@ -85,7 +86,7 @@ pub enum Color {
|
||||||
///
|
///
|
||||||
/// If you need to do custom work not covered by this enum, you can drop to
|
/// If you need to do custom work not covered by this enum, you can drop to
|
||||||
/// the Objective-C level yourself and wrap your color in this.
|
/// the Objective-C level yourself and wrap your color in this.
|
||||||
Custom(Arc<RwLock<Id<Object>>>),
|
Custom(Arc<RwLock<Id<Object, Owned>>>),
|
||||||
|
|
||||||
/// The system-provided black. Harsh - you probably don't want to use this.
|
/// The system-provided black. Harsh - you probably don't want to use this.
|
||||||
SystemBlack,
|
SystemBlack,
|
||||||
|
@ -247,9 +248,9 @@ impl Color {
|
||||||
let b = blue as CGFloat / 255.0;
|
let b = blue as CGFloat / 255.0;
|
||||||
let a = alpha as CGFloat / 255.0;
|
let a = alpha as CGFloat / 255.0;
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
let ptr = unsafe { Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedRed:r green:g blue:b alpha:a]) };
|
let ptr = unsafe { msg_send_id![class!(NSColor), colorWithCalibratedRed: r, green: g, blue: b, alpha: a] };
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
let ptr = unsafe { Id::from_ptr(msg_send![class!(UIColor), colorWithRed:r green:g blue:b alpha:a]) };
|
let ptr = unsafe { msg_send_id![class!(UIColor), colorWithRed: r, green: g, blue: b, alpha: a] };
|
||||||
|
|
||||||
Color::Custom(Arc::new(RwLock::new(ptr)))
|
Color::Custom(Arc::new(RwLock::new(ptr)))
|
||||||
}
|
}
|
||||||
|
@ -271,12 +272,18 @@ impl Color {
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
Color::Custom(Arc::new(RwLock::new(unsafe {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
{
|
{
|
||||||
Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedHue:h saturation:s brightness:b alpha:a])
|
msg_send_id![
|
||||||
|
class!(NSColor),
|
||||||
|
colorWithCalibratedHue: h,
|
||||||
|
saturation: s,
|
||||||
|
brightness: b,
|
||||||
|
alpha: a
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
{
|
{
|
||||||
Id::from_ptr(msg_send![class!(UIColor), colorWithHue:h saturation:s brightness:b alpha:a])
|
msg_send_id![class!(UIColor), colorWithHue: h, saturation: s, brightness: b, alpha: a]
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -293,12 +300,12 @@ impl Color {
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
Color::Custom(Arc::new(RwLock::new(unsafe {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
{
|
{
|
||||||
Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedWhite:level alpha:alpha])
|
msg_send_id![class!(NSColor), colorWithCalibratedWhite: level, alpha: alpha]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
{
|
{
|
||||||
Id::from_ptr(msg_send![class!(UIColor), colorWithWhite:level alpha:alpha])
|
msg_send_id![class!(UIColor), colorWithWhite: level, alpha: alpha]
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -345,49 +352,37 @@ impl Color {
|
||||||
// am happy to do this for now and let someone who needs true dynamic allocation look into
|
// am happy to do this for now and let someone who needs true dynamic allocation look into
|
||||||
// it and PR it.
|
// it and PR it.
|
||||||
Color::Custom(Arc::new(RwLock::new(unsafe {
|
Color::Custom(Arc::new(RwLock::new(unsafe {
|
||||||
let color: id = msg_send![appkit_dynamic_color::register_class(), new];
|
let mut color: Id<Object, Owned> = msg_send_id![appkit_dynamic_color::register_class(), new];
|
||||||
|
|
||||||
(&mut *color).set_ivar(AQUA_LIGHT_COLOR_NORMAL_CONTRAST, {
|
color.set_ivar(AQUA_LIGHT_COLOR_NORMAL_CONTRAST, {
|
||||||
let color: id = handler(Style {
|
to_objc(&handler(Style {
|
||||||
theme: Theme::Light,
|
theme: Theme::Light,
|
||||||
contrast: Contrast::Normal
|
contrast: Contrast::Normal
|
||||||
})
|
}))
|
||||||
.into();
|
|
||||||
|
|
||||||
color
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(&mut *color).set_ivar(AQUA_LIGHT_COLOR_HIGH_CONTRAST, {
|
color.set_ivar(AQUA_LIGHT_COLOR_HIGH_CONTRAST, {
|
||||||
let color: id = handler(Style {
|
to_objc(&handler(Style {
|
||||||
theme: Theme::Light,
|
theme: Theme::Light,
|
||||||
contrast: Contrast::High
|
contrast: Contrast::High
|
||||||
})
|
}))
|
||||||
.into();
|
|
||||||
|
|
||||||
color
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(&mut *color).set_ivar(AQUA_DARK_COLOR_NORMAL_CONTRAST, {
|
color.set_ivar(AQUA_DARK_COLOR_NORMAL_CONTRAST, {
|
||||||
let color: id = handler(Style {
|
to_objc(&handler(Style {
|
||||||
theme: Theme::Dark,
|
theme: Theme::Dark,
|
||||||
contrast: Contrast::Normal
|
contrast: Contrast::Normal
|
||||||
})
|
}))
|
||||||
.into();
|
|
||||||
|
|
||||||
color
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(&mut *color).set_ivar(AQUA_DARK_COLOR_HIGH_CONTRAST, {
|
color.set_ivar(AQUA_DARK_COLOR_HIGH_CONTRAST, {
|
||||||
let color: id = handler(Style {
|
to_objc(&handler(Style {
|
||||||
theme: Theme::Light,
|
theme: Theme::Light,
|
||||||
contrast: Contrast::Normal
|
contrast: Contrast::Normal
|
||||||
})
|
}))
|
||||||
.into();
|
|
||||||
|
|
||||||
color
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Id::from_ptr(color)
|
color
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,10 +393,9 @@ impl Color {
|
||||||
/// you're not using a cached version of this unless you explicitly want the _same_ color
|
/// you're not using a cached version of this unless you explicitly want the _same_ color
|
||||||
/// in every context it's used in.
|
/// in every context it's used in.
|
||||||
pub fn cg_color(&self) -> CGColor {
|
pub fn cg_color(&self) -> CGColor {
|
||||||
// @TODO: This should probably return a CGColorRef...
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let objc: id = self.into();
|
let objc: id = self.into();
|
||||||
msg_send![objc, CGColor]
|
CGColor::wrap_under_get_rule(msg_send![objc, CGColor])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,15 +408,8 @@ impl AsRef<Color> for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Color> for id {
|
|
||||||
/// Consumes and returns the pointer to the underlying Color.
|
|
||||||
fn from(color: Color) -> Self {
|
|
||||||
unsafe { to_objc(&color) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Color> for id {
|
impl From<&Color> for id {
|
||||||
/// Consumes and returns the pointer to the underlying Color.
|
/// Returns the pointer to the underlying Color.
|
||||||
fn from(color: &Color) -> Self {
|
fn from(color: &Color) -> Self {
|
||||||
unsafe { to_objc(color) }
|
unsafe { to_objc(color) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, NSUInteger, NO, YES};
|
use crate::foundation::{id, NSUInteger, NO, YES};
|
||||||
use crate::objc_access::ObjcAccess;
|
use crate::objc_access::ObjcAccess;
|
||||||
|
|
|
@ -34,9 +34,9 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, to_bool, NSData, NSMutableDictionary, NSNumber, NSString, BOOL, NO, YES};
|
use crate::foundation::{id, nil, to_bool, NSData, NSMutableDictionary, NSNumber, NSString, BOOL, NO, YES};
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ pub use value::Value;
|
||||||
///
|
///
|
||||||
/// This should not be used for sensitive data - use the Keychain for that.
|
/// This should not be used for sensitive data - use the Keychain for that.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UserDefaults(pub Id<Object>);
|
pub struct UserDefaults(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Default for UserDefaults {
|
impl Default for UserDefaults {
|
||||||
/// Equivalent to calling `UserDefaults::standard()`.
|
/// Equivalent to calling `UserDefaults::standard()`.
|
||||||
|
@ -71,7 +71,7 @@ impl UserDefaults {
|
||||||
/// let _ = defaults.get("test");
|
/// let _ = defaults.get("test");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn standard() -> Self {
|
pub fn standard() -> Self {
|
||||||
UserDefaults(unsafe { Id::from_ptr(msg_send![class!(NSUserDefaults), standardUserDefaults]) })
|
UserDefaults(unsafe { msg_send_id![class!(NSUserDefaults), standardUserDefaults] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a user defaults instance for the given suite name. You typically use this to share
|
/// Returns a user defaults instance for the given suite name. You typically use this to share
|
||||||
|
@ -89,8 +89,8 @@ impl UserDefaults {
|
||||||
let name = NSString::new(named);
|
let name = NSString::new(named);
|
||||||
|
|
||||||
UserDefaults(unsafe {
|
UserDefaults(unsafe {
|
||||||
let alloc: id = msg_send![class!(NSUserDefaults), alloc];
|
let alloc = msg_send_id![class!(NSUserDefaults), alloc];
|
||||||
Id::from_ptr(msg_send![alloc, initWithSuiteName:&*name])
|
msg_send_id![alloc, initWithSuiteName:&*name]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +130,10 @@ impl UserDefaults {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn insert<K: AsRef<str>>(&mut self, key: K, value: Value) {
|
pub fn insert<K: AsRef<str>>(&mut self, key: K, value: Value) {
|
||||||
let key = NSString::new(key.as_ref());
|
let key = NSString::new(key.as_ref());
|
||||||
let value: id = value.into();
|
let value: id = &mut *value.into_id();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, setObject:value forKey:key];
|
let _: () = msg_send![&*self.0, setObject: value, forKey: &*key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ impl UserDefaults {
|
||||||
//
|
//
|
||||||
// For context: https://nshipster.com/type-encodings/
|
// For context: https://nshipster.com/type-encodings/
|
||||||
if NSNumber::is(result) {
|
if NSNumber::is(result) {
|
||||||
let number = NSNumber::wrap(result);
|
let number = NSNumber::retain(result);
|
||||||
|
|
||||||
return match number.objc_type() {
|
return match number.objc_type() {
|
||||||
"c" => Some(Value::Bool(number.as_bool())),
|
"c" => Some(Value::Bool(number.as_bool())),
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use objc::{
|
||||||
|
rc::{Id, Owned, Shared},
|
||||||
|
runtime::Object
|
||||||
|
};
|
||||||
|
|
||||||
use crate::foundation::{id, NSData, NSMutableDictionary, NSNumber, NSString};
|
use crate::foundation::{id, NSData, NSMutableDictionary, NSNumber, NSString};
|
||||||
|
|
||||||
/// Represents a Value that can be stored or queried with `UserDefaults`.
|
/// Represents a Value that can be stored or queried with `UserDefaults`.
|
||||||
|
@ -128,19 +133,17 @@ impl Value {
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Value> for id {
|
|
||||||
/// Shepherds `Value` types into `NSObject`s that can be stored in `NSUserDefaults`.
|
/// Shepherds `Value` types into `NSObject`s that can be stored in `NSUserDefaults`.
|
||||||
// These currently work, but may not be exhaustive and should be looked over past the preview
|
// These currently work, but may not be exhaustive and should be looked over past the preview
|
||||||
// period.
|
// period.
|
||||||
fn from(value: Value) -> Self {
|
pub fn into_id(self) -> Id<Object, Owned> {
|
||||||
match value {
|
match self {
|
||||||
Value::Bool(b) => NSNumber::bool(b).into(),
|
Value::Bool(b) => NSNumber::bool(b).0,
|
||||||
Value::String(s) => NSString::new(&s).into(),
|
Value::String(s) => NSString::new(&s).objc,
|
||||||
Value::Float(f) => NSNumber::float(f).into(),
|
Value::Float(f) => NSNumber::float(f).0,
|
||||||
Value::Integer(i) => NSNumber::integer(i).into(),
|
Value::Integer(i) => NSNumber::integer(i).0,
|
||||||
Value::Data(data) => NSData::new(data).into()
|
Value::Data(data) => NSData::new(data).0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +158,7 @@ where
|
||||||
|
|
||||||
for (key, value) in map.into_iter() {
|
for (key, value) in map.into_iter() {
|
||||||
let k = NSString::new(key.as_ref());
|
let k = NSString::new(key.as_ref());
|
||||||
dictionary.insert(k, value.into());
|
dictionary.insert(k, &mut *value.into_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
dictionary
|
dictionary
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
//! across the codebase, hence why they're here - they're not currently exhaustive, so feel free to
|
//! across the codebase, hence why they're here - they're not currently exhaustive, so feel free to
|
||||||
//! tinker and pull request.
|
//! tinker and pull request.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::NSUInteger;
|
use crate::foundation::NSUInteger;
|
||||||
use crate::pasteboard::Pasteboard;
|
use crate::pasteboard::Pasteboard;
|
||||||
|
@ -54,7 +54,7 @@ impl From<DragOperation> for NSUInteger {
|
||||||
/// this only provides getters - merely a Rust-y way to grab what you need.
|
/// this only provides getters - merely a Rust-y way to grab what you need.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DragInfo {
|
pub struct DragInfo {
|
||||||
pub info: ShareId<Object>
|
pub info: Id<Object, Shared>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DragInfo {
|
impl DragInfo {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSInteger, NSString};
|
use crate::foundation::{id, nil, NSInteger, NSString};
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ impl Error {
|
||||||
unsafe {
|
unsafe {
|
||||||
let domain = NSString::new(&self.domain);
|
let domain = NSString::new(&self.domain);
|
||||||
let code = self.code as NSInteger;
|
let code = self.code as NSInteger;
|
||||||
msg_send![class!(NSError), errorWithDomain:domain code:code userInfo:nil]
|
msg_send![class!(NSError), errorWithDomain: &*domain, code: code, userInfo: nil]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::{Object, BOOL};
|
use objc::runtime::{Object, BOOL};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::error::Error as AppKitError;
|
use crate::error::Error as AppKitError;
|
||||||
|
@ -18,17 +18,16 @@ use crate::foundation::{id, nil, NSString, NSUInteger, NO};
|
||||||
/// If your app is not sandboxed, you can use your favorite Rust library -
|
/// If your app is not sandboxed, you can use your favorite Rust library -
|
||||||
/// but if you _are_ operating in the sandbox, there's a good chance you'll want to use this.
|
/// but if you _are_ operating in the sandbox, there's a good chance you'll want to use this.
|
||||||
///
|
///
|
||||||
/// @TODO: Couldn't this just be a ShareId?
|
/// @TODO: Couldn't this just be a Id<Object, Shared>?
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct FileManager(pub Arc<RwLock<Id<Object>>>);
|
pub struct FileManager(pub Arc<RwLock<Id<Object, Owned>>>);
|
||||||
|
|
||||||
impl Default for FileManager {
|
impl Default for FileManager {
|
||||||
/// Returns a default file manager, which maps to the default system file manager. For common
|
/// Returns a default file manager, which maps to the default system file manager. For common
|
||||||
/// and simple tasks, with no callbacks, you might want this.
|
/// and simple tasks, with no callbacks, you might want this.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FileManager(Arc::new(RwLock::new(unsafe {
|
FileManager(Arc::new(RwLock::new(unsafe {
|
||||||
let manager: id = msg_send![class!(NSFileManager), defaultManager];
|
msg_send_id![class!(NSFileManager), defaultManager]
|
||||||
Id::from_ptr(manager)
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,10 +35,7 @@ impl Default for FileManager {
|
||||||
impl FileManager {
|
impl FileManager {
|
||||||
/// Returns a new FileManager that opts in to delegate methods.
|
/// Returns a new FileManager that opts in to delegate methods.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
FileManager(Arc::new(RwLock::new(unsafe {
|
FileManager(Arc::new(RwLock::new(unsafe { msg_send_id![class!(NSFileManager), new] })))
|
||||||
let manager: id = msg_send![class!(NSFileManager), new];
|
|
||||||
Id::from_ptr(manager)
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a directory/domain combination, will attempt to get the directory that matches.
|
/// Given a directory/domain combination, will attempt to get the directory that matches.
|
||||||
|
|
|
@ -4,19 +4,19 @@
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSInteger, NSString, NO, YES};
|
use crate::foundation::{id, nil, NSInteger, NSString, NO, YES};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FileSavePanel {
|
pub struct FileSavePanel {
|
||||||
/// The internal Objective C `NSOpenPanel` instance.
|
/// The internal Objective C `NSOpenPanel` instance.
|
||||||
pub panel: ShareId<Object>,
|
pub panel: Id<Object, Shared>,
|
||||||
|
|
||||||
/// The internal `NSObject` that routes delegate callbacks around.
|
/// The internal `NSObject` that routes delegate callbacks around.
|
||||||
pub delegate: ShareId<Object>,
|
pub delegate: Id<Object, Shared>,
|
||||||
|
|
||||||
/// Whether the user can choose files. Defaults to `true`.
|
/// Whether the user can choose files. Defaults to `true`.
|
||||||
pub can_create_directories: bool
|
pub can_create_directories: bool
|
||||||
|
@ -35,11 +35,10 @@ impl FileSavePanel {
|
||||||
FileSavePanel {
|
FileSavePanel {
|
||||||
panel: unsafe {
|
panel: unsafe {
|
||||||
let cls = class!(NSSavePanel);
|
let cls = class!(NSSavePanel);
|
||||||
let x: id = msg_send![cls, savePanel];
|
msg_send_id![cls, savePanel]
|
||||||
ShareId::from_ptr(x)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
delegate: unsafe { ShareId::from_ptr(msg_send![class!(NSObject), new]) },
|
delegate: unsafe { msg_send_id![class!(NSObject), new] },
|
||||||
|
|
||||||
can_create_directories: true
|
can_create_directories: true
|
||||||
}
|
}
|
||||||
|
@ -95,7 +94,7 @@ impl FileSavePanel {
|
||||||
let _: () = msg_send![&*self.panel, runModal];
|
let _: () = msg_send![&*self.panel, runModal];
|
||||||
completion.call((1,));
|
completion.call((1,));
|
||||||
//beginWithCompletionHandler:completion.copy()];
|
//beginWithCompletionHandler:completion.copy()];
|
||||||
//let _: () = msg_send![&*self.panel, beginWithCompletionHandler:completion.copy()];
|
//let _: () = msg_send![&*self.panel, beginWithCompletionHandler: &*completion.copy()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::filesystem::enums::ModalResponse;
|
use crate::filesystem::enums::ModalResponse;
|
||||||
use crate::foundation::{id, nil, NSInteger, NSString, NO, NSURL, YES};
|
use crate::foundation::{id, nil, NSInteger, NSString, NO, NSURL, YES};
|
||||||
|
@ -19,10 +19,10 @@ use crate::appkit::window::{Window, WindowDelegate};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FileSelectPanel {
|
pub struct FileSelectPanel {
|
||||||
/// The internal Objective C `NSOpenPanel` instance.
|
/// The internal Objective C `NSOpenPanel` instance.
|
||||||
pub panel: ShareId<Object>,
|
pub panel: Id<Object, Shared>,
|
||||||
|
|
||||||
/// The internal `NSObject` that routes delegate callbacks around.
|
/// The internal `NSObject` that routes delegate callbacks around.
|
||||||
pub delegate: ShareId<Object>,
|
pub delegate: Id<Object, Shared>,
|
||||||
|
|
||||||
/// Whether the user can choose files. Defaults to `true`.
|
/// Whether the user can choose files. Defaults to `true`.
|
||||||
pub can_choose_files: bool,
|
pub can_choose_files: bool,
|
||||||
|
@ -54,11 +54,10 @@ impl FileSelectPanel {
|
||||||
FileSelectPanel {
|
FileSelectPanel {
|
||||||
panel: unsafe {
|
panel: unsafe {
|
||||||
let cls = class!(NSOpenPanel);
|
let cls = class!(NSOpenPanel);
|
||||||
let x: id = msg_send![cls, openPanel];
|
msg_send_id![cls, openPanel]
|
||||||
ShareId::from_ptr(x)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
delegate: unsafe { ShareId::from_ptr(msg_send![class!(NSObject), new]) },
|
delegate: unsafe { msg_send_id![class!(NSObject), new] },
|
||||||
|
|
||||||
can_choose_files: true,
|
can_choose_files: true,
|
||||||
can_choose_directories: false,
|
can_choose_directories: false,
|
||||||
|
@ -148,7 +147,7 @@ impl FileSelectPanel {
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.panel, beginWithCompletionHandler:completion.copy()];
|
let _: () = msg_send![&*self.panel, beginWithCompletionHandler: &*completion.copy()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +183,11 @@ impl FileSelectPanel {
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.panel, beginSheetModalForWindow:&*window.objc completionHandler:completion.copy()];
|
let _: () = msg_send![
|
||||||
|
&*self.panel,
|
||||||
|
beginSheetModalForWindow: &*window.objc,
|
||||||
|
completionHandler: &*completion.copy(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
|
@ -11,29 +11,24 @@ use crate::foundation::id;
|
||||||
/// ever deemed necessary (unlikely, given how much Apple has optimized the Foundation classes, but
|
/// ever deemed necessary (unlikely, given how much Apple has optimized the Foundation classes, but
|
||||||
/// still...).
|
/// still...).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NSArray(pub Id<Object>);
|
pub struct NSArray(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl NSArray {
|
impl NSArray {
|
||||||
/// Given a set of `Object`s, creates and retains an `NSArray` that holds them.
|
/// Given a set of `Object`s, creates and retains an `NSArray` that holds them.
|
||||||
pub fn new(objects: &[id]) -> Self {
|
pub fn new(objects: &[id]) -> Self {
|
||||||
NSArray(unsafe {
|
NSArray(unsafe {
|
||||||
Id::from_ptr(msg_send![class!(NSArray),
|
msg_send_id![
|
||||||
arrayWithObjects:objects.as_ptr()
|
class!(NSArray),
|
||||||
count:objects.len()
|
arrayWithObjects: objects.as_ptr(),
|
||||||
])
|
count: objects.len()
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In some cases, we're vended an `NSArray` by the system that we need to call retain on.
|
/// In some cases, we're vended an `NSArray` by the system that we need to call retain on.
|
||||||
/// This handles that case.
|
/// This handles that case.
|
||||||
pub fn retain(array: id) -> Self {
|
pub fn retain(array: id) -> Self {
|
||||||
NSArray(unsafe { Id::from_ptr(array) })
|
NSArray(unsafe { Id::retain(array).unwrap() })
|
||||||
}
|
|
||||||
|
|
||||||
/// In some cases, we're vended an `NSArray` by the system, and it's ideal to not retain that.
|
|
||||||
/// This handles that edge case.
|
|
||||||
pub fn from_retained(array: id) -> Self {
|
|
||||||
NSArray(unsafe { Id::from_retained_ptr(array) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `count` (`len()` equivalent) for the backing `NSArray`.
|
/// Returns the `count` (`len()` equivalent) for the backing `NSArray`.
|
||||||
|
@ -83,10 +78,11 @@ impl From<Vec<&Object>> for NSArray {
|
||||||
/// Given a set of `Object`s, creates an `NSArray` that holds them.
|
/// Given a set of `Object`s, creates an `NSArray` that holds them.
|
||||||
fn from(objects: Vec<&Object>) -> Self {
|
fn from(objects: Vec<&Object>) -> Self {
|
||||||
NSArray(unsafe {
|
NSArray(unsafe {
|
||||||
Id::from_ptr(msg_send![class!(NSArray),
|
msg_send_id![
|
||||||
arrayWithObjects:objects.as_ptr()
|
class!(NSArray),
|
||||||
count:objects.len()
|
arrayWithObjects: objects.as_ptr(),
|
||||||
])
|
count: objects.len(),
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,21 +91,15 @@ impl From<Vec<id>> for NSArray {
|
||||||
/// Given a set of `*mut Object`s, creates an `NSArray` that holds them.
|
/// Given a set of `*mut Object`s, creates an `NSArray` that holds them.
|
||||||
fn from(objects: Vec<id>) -> Self {
|
fn from(objects: Vec<id>) -> Self {
|
||||||
NSArray(unsafe {
|
NSArray(unsafe {
|
||||||
Id::from_ptr(msg_send![class!(NSArray),
|
msg_send_id![
|
||||||
arrayWithObjects:objects.as_ptr()
|
class!(NSArray),
|
||||||
count:objects.len()
|
arrayWithObjects: objects.as_ptr(),
|
||||||
])
|
count: objects.len()
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NSArray> for id {
|
|
||||||
/// Consumes and returns the pointer to the underlying NSArray.
|
|
||||||
fn from(mut array: NSArray) -> Self {
|
|
||||||
&mut *array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for NSArray {
|
impl Deref for NSArray {
|
||||||
type Target = Object;
|
type Target = Object;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
/// A wrapper around `NSAutoReleasePool`. The core `App` structures create and manage one of these,
|
/// A wrapper around `NSAutoReleasePool`. The core `App` structures create and manage one of these,
|
||||||
/// but it's conceivable that users might need to create their own.
|
/// but it's conceivable that users might need to create their own.
|
||||||
|
@ -8,13 +8,13 @@ use objc_id::Id;
|
||||||
/// When this is dropped, we automatically send a `drain` message to the underlying pool. You can
|
/// When this is dropped, we automatically send a `drain` message to the underlying pool. You can
|
||||||
/// also call `drain()` yourself if you need to drain for whatever reason.
|
/// also call `drain()` yourself if you need to drain for whatever reason.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AutoReleasePool(pub Id<Object>);
|
pub struct AutoReleasePool(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl AutoReleasePool {
|
impl AutoReleasePool {
|
||||||
/// Creates and returns a new `AutoReleasePool`. You need to take care to keep this alive for
|
/// Creates and returns a new `AutoReleasePool`. You need to take care to keep this alive for
|
||||||
/// as long as you need it.
|
/// as long as you need it.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
AutoReleasePool(unsafe { Id::from_retained_ptr(msg_send![class!(NSAutoreleasePool), new]) })
|
AutoReleasePool(unsafe { msg_send_id![class!(NSAutoreleasePool), new] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drains the underlying AutoreleasePool.
|
/// Drains the underlying AutoreleasePool.
|
||||||
|
|
|
@ -9,7 +9,8 @@ use std::time::Instant;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{objc_getClass, Class};
|
use objc::ffi;
|
||||||
|
use objc::runtime::Class;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref CLASSES: ClassMap = ClassMap::new();
|
static ref CLASSES: ClassMap = ClassMap::new();
|
||||||
|
@ -59,7 +60,7 @@ impl ClassMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A publicly accessible load method that just passes through our global singleton.
|
/// A publicly accessible load method that just passes through our global singleton.
|
||||||
pub fn static_load(class_name: &'static str, superclass_name: Option<&'static str>) -> Option<*const Class> {
|
pub fn static_load(class_name: &'static str, superclass_name: Option<&'static str>) -> Option<&'static Class> {
|
||||||
CLASSES.load(class_name, superclass_name)
|
CLASSES.load(class_name, superclass_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +68,12 @@ impl ClassMap {
|
||||||
///
|
///
|
||||||
/// This checks our internal map first, and then calls out to the Objective-C runtime to ensure
|
/// This checks our internal map first, and then calls out to the Objective-C runtime to ensure
|
||||||
/// we're not missing anything.
|
/// we're not missing anything.
|
||||||
pub fn load(&self, class_name: &'static str, superclass_name: Option<&'static str>) -> Option<*const Class> {
|
pub fn load(&self, class_name: &'static str, superclass_name: Option<&'static str>) -> Option<&'static Class> {
|
||||||
{
|
{
|
||||||
let reader = self.0.read().unwrap();
|
let reader = self.0.read().unwrap();
|
||||||
if let Some(entry) = (*reader).get(&(class_name, superclass_name)) {
|
if let Some(entry) = (*reader).get(&(class_name, superclass_name)) {
|
||||||
let ptr = &entry.ptr;
|
let ptr = &entry.ptr;
|
||||||
return Some(*ptr as *const Class);
|
return Some(unsafe { &*(*ptr as *const Class) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ impl ClassMap {
|
||||||
// runtime, and we can wind up in a situation where we're attempting to register a Class
|
// runtime, and we can wind up in a situation where we're attempting to register a Class
|
||||||
// that already exists but we can't see.
|
// that already exists but we can't see.
|
||||||
let objc_class_name = CString::new(class_name).unwrap();
|
let objc_class_name = CString::new(class_name).unwrap();
|
||||||
let class = unsafe { objc_getClass(objc_class_name.as_ptr() as *const _) };
|
let class = unsafe { ffi::objc_getClass(objc_class_name.as_ptr() as *const _) };
|
||||||
|
|
||||||
// This should not happen for our use-cases, but it's conceivable that this could actually
|
// This should not happen for our use-cases, but it's conceivable that this could actually
|
||||||
// be expected, so just return None and let the caller panic if so desired.
|
// be expected, so just return None and let the caller panic if so desired.
|
||||||
|
@ -101,7 +102,7 @@ impl ClassMap {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(class)
|
Some(unsafe { class.cast::<Class>().as_ref() }.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store a newly created subclass type.
|
/// Store a newly created subclass type.
|
||||||
|
@ -129,7 +130,7 @@ impl ClassMap {
|
||||||
/// > class name - but most cases do not need this and it would be a larger change to orchestrate at
|
/// > class name - but most cases do not need this and it would be a larger change to orchestrate at
|
||||||
/// > the moment.
|
/// > the moment.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn load_or_register_class<F>(superclass_name: &'static str, subclass_name: &'static str, config: F) -> *const Class
|
pub fn load_or_register_class<F>(superclass_name: &'static str, subclass_name: &'static str, config: F) -> &'static Class
|
||||||
where
|
where
|
||||||
F: Fn(&mut ClassDecl) + 'static
|
F: Fn(&mut ClassDecl) + 'static
|
||||||
{
|
{
|
||||||
|
@ -155,7 +156,7 @@ pub fn load_or_register_class_with_optional_generated_suffix<F>(
|
||||||
subclass_name: &'static str,
|
subclass_name: &'static str,
|
||||||
should_append_random_subclass_name_suffix: bool,
|
should_append_random_subclass_name_suffix: bool,
|
||||||
config: F
|
config: F
|
||||||
) -> *const Class
|
) -> &'static Class
|
||||||
where
|
where
|
||||||
F: Fn(&mut ClassDecl) + 'static
|
F: Fn(&mut ClassDecl) + 'static
|
||||||
{
|
{
|
||||||
|
@ -188,7 +189,7 @@ where
|
||||||
false => format!("{}_{}", subclass_name, superclass_name)
|
false => format!("{}_{}", subclass_name, superclass_name)
|
||||||
};
|
};
|
||||||
|
|
||||||
match ClassDecl::new(&objc_subclass_name, unsafe { &*superclass }) {
|
match ClassDecl::new(&objc_subclass_name, superclass) {
|
||||||
Some(mut decl) => {
|
Some(mut decl) => {
|
||||||
config(&mut decl);
|
config(&mut decl);
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ use std::slice;
|
||||||
|
|
||||||
use block::{Block, ConcreteBlock};
|
use block::{Block, ConcreteBlock};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, to_bool, NSUInteger, BOOL, NO, YES};
|
use crate::foundation::{id, to_bool, NSUInteger, BOOL, NO, YES};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use crate::foundation::{id, to_bool, NSUInteger, BOOL, NO, YES};
|
||||||
///
|
///
|
||||||
/// This is an intentionally limited API.
|
/// This is an intentionally limited API.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NSData(pub Id<Object>);
|
pub struct NSData(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl NSData {
|
impl NSData {
|
||||||
/// Given a vector of bytes, creates, retains, and returns a wrapped `NSData`.
|
/// Given a vector of bytes, creates, retains, and returns a wrapped `NSData`.
|
||||||
|
@ -41,12 +41,15 @@ impl NSData {
|
||||||
let bytes_ptr = bytes.as_mut_ptr() as *mut c_void;
|
let bytes_ptr = bytes.as_mut_ptr() as *mut c_void;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj: id = msg_send![class!(NSData), alloc];
|
let obj = msg_send_id![class!(NSData), alloc];
|
||||||
let obj: id = msg_send![obj, initWithBytesNoCopy:bytes_ptr
|
let obj = msg_send_id![
|
||||||
length:bytes.len()
|
obj,
|
||||||
deallocator:dealloc];
|
initWithBytesNoCopy: bytes_ptr,
|
||||||
|
length: bytes.len(),
|
||||||
|
deallocator: dealloc,
|
||||||
|
];
|
||||||
mem::forget(bytes);
|
mem::forget(bytes);
|
||||||
NSData(Id::from_ptr(obj))
|
NSData(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,20 +63,18 @@ impl NSData {
|
||||||
let bytes_ptr = bytes.as_ptr() as *mut c_void;
|
let bytes_ptr = bytes.as_ptr() as *mut c_void;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj: id = msg_send![class!(NSData), dataWithBytes:bytes_ptr length:bytes.len()];
|
let obj = msg_send_id![
|
||||||
NSData(Id::from_ptr(obj))
|
class!(NSData),
|
||||||
|
dataWithBytes: bytes_ptr,
|
||||||
|
length: bytes.len(),
|
||||||
|
];
|
||||||
|
NSData(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a (presumably) `NSData`, wraps and retains it.
|
/// Given a (presumably) `NSData`, wraps and retains it.
|
||||||
pub fn retain(data: id) -> Self {
|
pub fn retain(data: id) -> Self {
|
||||||
NSData(unsafe { Id::from_ptr(data) })
|
NSData(unsafe { Id::retain(data).unwrap() })
|
||||||
}
|
|
||||||
|
|
||||||
/// If we're vended an NSData from a method (e.g, a push notification token) we might want to
|
|
||||||
/// wrap it while we figure out what to do with it. This does that.
|
|
||||||
pub fn from_retained(data: id) -> Self {
|
|
||||||
NSData(unsafe { Id::from_retained_ptr(data) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper method for determining if a given `NSObject` is an `NSData`.
|
/// A helper method for determining if a given `NSObject` is an `NSData`.
|
||||||
|
@ -127,13 +128,6 @@ impl NSData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NSData> for id {
|
|
||||||
/// Consumes and returns the underlying `NSData`.
|
|
||||||
fn from(mut data: NSData) -> Self {
|
|
||||||
&mut *data.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for NSData {
|
impl Deref for NSData {
|
||||||
type Target = Object;
|
type Target = Object;
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
|
|
||||||
/// A wrapper for `NSMutableDictionary`.
|
/// A wrapper for `NSMutableDictionary`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NSMutableDictionary(pub Id<Object>);
|
pub struct NSMutableDictionary(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Default for NSMutableDictionary {
|
impl Default for NSMutableDictionary {
|
||||||
/// Returns a blank NSMutableDictionary.
|
/// Returns a blank NSMutableDictionary.
|
||||||
|
@ -26,7 +26,7 @@ impl NSMutableDictionary {
|
||||||
/// object model. You can, of course, bypass it and `msg_send![]` yourself, but it'd require an
|
/// object model. You can, of course, bypass it and `msg_send![]` yourself, but it'd require an
|
||||||
/// `unsafe {}` block... so you'll know you're in special territory then.
|
/// `unsafe {}` block... so you'll know you're in special territory then.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
NSMutableDictionary(unsafe { Id::from_ptr(msg_send![class!(NSMutableDictionary), new]) })
|
NSMutableDictionary(unsafe { msg_send_id![class!(NSMutableDictionary), new] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts an object into the backing NSMutablyDictionary.
|
/// Inserts an object into the backing NSMutablyDictionary.
|
||||||
|
@ -37,11 +37,6 @@ impl NSMutableDictionary {
|
||||||
let _: () = msg_send![&*self.0, setObject:object forKey:&*key];
|
let _: () = msg_send![&*self.0, setObject:object forKey:&*key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes and returns the underlying `NSMutableDictionary`.
|
|
||||||
pub fn into_inner(mut self) -> id {
|
|
||||||
&mut *self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for NSMutableDictionary {
|
impl Deref for NSMutableDictionary {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, to_bool, NSInteger, BOOL, NO, YES};
|
use crate::foundation::{id, to_bool, NSInteger, BOOL, NO, YES};
|
||||||
|
|
||||||
|
@ -12,39 +12,33 @@ use crate::foundation::{id, to_bool, NSInteger, BOOL, NO, YES};
|
||||||
/// In general we strive to avoid using this in the codebase, but it's a requirement for moving
|
/// In general we strive to avoid using this in the codebase, but it's a requirement for moving
|
||||||
/// objects in and out of certain situations (e.g, `UserDefaults`).
|
/// objects in and out of certain situations (e.g, `UserDefaults`).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NSNumber(pub Id<Object>);
|
pub struct NSNumber(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl NSNumber {
|
impl NSNumber {
|
||||||
/// If we're vended an NSNumber from a method (e.g, `NSUserDefaults` querying) we might want to
|
/// If we're vended an NSNumber from a method (e.g, `NSUserDefaults` querying) we might want to
|
||||||
/// wrap (and retain) it while we figure out what to do with it. This does that.
|
/// wrap (and retain) it while we figure out what to do with it. This does that.
|
||||||
pub fn retain(data: id) -> Self {
|
pub fn retain(data: id) -> Self {
|
||||||
NSNumber(unsafe { Id::from_ptr(data) })
|
NSNumber(unsafe { Id::retain(data).unwrap() })
|
||||||
}
|
|
||||||
|
|
||||||
/// If we're vended an NSNumber from a method (e.g, `NSUserDefaults` querying) we might want to
|
|
||||||
/// wrap it while we figure out what to do with it. This does that.
|
|
||||||
pub fn wrap(data: id) -> Self {
|
|
||||||
NSNumber(unsafe { Id::from_retained_ptr(data) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a `numberWithBool` instance of `NSNumber` and retains it.
|
/// Constructs a `numberWithBool` instance of `NSNumber` and retains it.
|
||||||
pub fn bool(value: bool) -> Self {
|
pub fn bool(value: bool) -> Self {
|
||||||
NSNumber(unsafe {
|
NSNumber(unsafe {
|
||||||
Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithBool:match value {
|
msg_send_id![class!(NSNumber), numberWithBool:match value {
|
||||||
true => YES,
|
true => YES,
|
||||||
false => NO
|
false => NO
|
||||||
}])
|
}]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a `numberWithInteger` instance of `NSNumber` and retains it.
|
/// Constructs a `numberWithInteger` instance of `NSNumber` and retains it.
|
||||||
pub fn integer(value: i64) -> Self {
|
pub fn integer(value: i64) -> Self {
|
||||||
NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithInteger: value as NSInteger]) })
|
NSNumber(unsafe { msg_send_id![class!(NSNumber), numberWithInteger: value as NSInteger] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a `numberWithDouble` instance of `NSNumber` and retains it.
|
/// Constructs a `numberWithDouble` instance of `NSNumber` and retains it.
|
||||||
pub fn float(value: f64) -> Self {
|
pub fn float(value: f64) -> Self {
|
||||||
NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithDouble: value]) })
|
NSNumber(unsafe { msg_send_id![class!(NSNumber), numberWithDouble: value] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `objCType` of the underlying `NSNumber` as a Rust `&str`. This flag can be used
|
/// Returns the `objCType` of the underlying `NSNumber` as a Rust `&str`. This flag can be used
|
||||||
|
@ -96,10 +90,3 @@ impl NSNumber {
|
||||||
to_bool(result)
|
to_bool(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NSNumber> for id {
|
|
||||||
/// Consumes and returns the underlying `NSNumber`.
|
|
||||||
fn from(mut number: NSNumber) -> Self {
|
|
||||||
&mut *number.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::{fmt, slice, str};
|
use std::{fmt, slice, str};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, to_bool, BOOL, NO, YES};
|
use crate::foundation::{id, to_bool, BOOL, NO, YES};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const UTF8_ENCODING: usize = 4;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NSString<'a> {
|
pub struct NSString<'a> {
|
||||||
/// A reference to the backing `NSString`.
|
/// A reference to the backing `NSString`.
|
||||||
pub objc: Id<Object>,
|
pub objc: Id<Object, Owned>,
|
||||||
phantom: PhantomData<&'a ()>
|
phantom: PhantomData<&'a ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,11 +27,12 @@ impl<'a> NSString<'a> {
|
||||||
pub fn new(s: &str) -> Self {
|
pub fn new(s: &str) -> Self {
|
||||||
NSString {
|
NSString {
|
||||||
objc: unsafe {
|
objc: unsafe {
|
||||||
let nsstring: *mut Object = msg_send![class!(NSString), alloc];
|
msg_send_id![
|
||||||
Id::from_ptr(msg_send![nsstring, initWithBytes:s.as_ptr()
|
msg_send_id![class!(NSString), alloc],
|
||||||
length:s.len()
|
initWithBytes: s.as_ptr(),
|
||||||
encoding:UTF8_ENCODING
|
length: s.len(),
|
||||||
])
|
encoding: UTF8_ENCODING,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
|
@ -42,12 +43,14 @@ impl<'a> NSString<'a> {
|
||||||
pub fn no_copy(s: &'a str) -> Self {
|
pub fn no_copy(s: &'a str) -> Self {
|
||||||
NSString {
|
NSString {
|
||||||
objc: unsafe {
|
objc: unsafe {
|
||||||
let nsstring: id = msg_send![class!(NSString), alloc];
|
let nsstring = msg_send_id![class!(NSString), alloc];
|
||||||
Id::from_ptr(msg_send![nsstring, initWithBytesNoCopy:s.as_ptr()
|
msg_send_id![
|
||||||
length:s.len()
|
nsstring,
|
||||||
encoding:UTF8_ENCODING
|
initWithBytesNoCopy: s.as_ptr(),
|
||||||
freeWhenDone:NO
|
length: s.len(),
|
||||||
])
|
encoding: UTF8_ENCODING,
|
||||||
|
freeWhenDone: NO,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
|
@ -58,15 +61,14 @@ impl<'a> NSString<'a> {
|
||||||
/// retain it.
|
/// retain it.
|
||||||
pub fn retain(object: id) -> Self {
|
pub fn retain(object: id) -> Self {
|
||||||
NSString {
|
NSString {
|
||||||
objc: unsafe { Id::from_ptr(object) },
|
objc: unsafe { Id::retain(object).unwrap() },
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In some cases, we want to wrap a system-provided NSString without retaining it.
|
pub fn from_id(objc: Id<Object, Owned>) -> Self {
|
||||||
pub fn from_retained(object: id) -> Self {
|
Self {
|
||||||
NSString {
|
objc,
|
||||||
objc: unsafe { Id::from_retained_ptr(object) },
|
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,13 +115,6 @@ impl fmt::Display for NSString<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NSString<'_>> for id {
|
|
||||||
/// Consumes and returns the pointer to the underlying NSString instance.
|
|
||||||
fn from(mut string: NSString) -> Self {
|
|
||||||
&mut *string.objc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for NSString<'_> {
|
impl Deref for NSString<'_> {
|
||||||
type Target = Object;
|
type Target = Object;
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSData, NSString, NSUInteger};
|
use crate::foundation::{id, nil, NSData, NSString, NSUInteger};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ pub use resource_keys::{NSURLFileResource, NSURLResourceKey, NSUbiquitousItemDow
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NSURL<'a> {
|
pub struct NSURL<'a> {
|
||||||
/// A reference to the backing `NSURL`.
|
/// A reference to the backing `NSURL`.
|
||||||
pub objc: ShareId<Object>,
|
pub objc: Id<Object, Shared>,
|
||||||
phantom: PhantomData<&'a ()>
|
phantom: PhantomData<&'a ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,15 +40,7 @@ impl<'a> NSURL<'a> {
|
||||||
/// retain it.
|
/// retain it.
|
||||||
pub fn retain(object: id) -> Self {
|
pub fn retain(object: id) -> Self {
|
||||||
NSURL {
|
NSURL {
|
||||||
objc: unsafe { ShareId::from_ptr(object) },
|
objc: unsafe { Id::retain(object).unwrap() },
|
||||||
phantom: PhantomData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// In some cases, we want to wrap a system-provided NSURL without retaining it.
|
|
||||||
pub fn from_retained(object: id) -> Self {
|
|
||||||
NSURL {
|
|
||||||
objc: unsafe { ShareId::from_retained_ptr(object) },
|
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +50,7 @@ impl<'a> NSURL<'a> {
|
||||||
let url = NSString::new(url);
|
let url = NSString::new(url);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
objc: unsafe { ShareId::from_ptr(msg_send![class!(NSURL), URLWithString:&*url]) },
|
objc: unsafe { msg_send_id![class!(NSURL), URLWithString:&*url] },
|
||||||
|
|
||||||
phantom: PhantomData
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
|
@ -105,18 +97,22 @@ impl<'a> NSURL<'a> {
|
||||||
// Mutability woes mean we just go through a match here to satisfy message passing needs.
|
// Mutability woes mean we just go through a match here to satisfy message passing needs.
|
||||||
let bookmark_data = NSData::retain(match relative_to_url {
|
let bookmark_data = NSData::retain(match relative_to_url {
|
||||||
Some(relative_url) => unsafe {
|
Some(relative_url) => unsafe {
|
||||||
msg_send![&*self.objc, bookmarkDataWithOptions:opts
|
msg_send![
|
||||||
includingResourceValuesForKeys:resource_keys
|
&*self.objc,
|
||||||
relativeToURL:relative_url
|
bookmarkDataWithOptions: opts,
|
||||||
error:nil
|
includingResourceValuesForKeys: resource_keys,
|
||||||
|
relativeToURL: &*relative_url,
|
||||||
|
error: nil,
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
None => unsafe {
|
None => unsafe {
|
||||||
msg_send![&*self.objc, bookmarkDataWithOptions:opts
|
msg_send![
|
||||||
includingResourceValuesForKeys:resource_keys
|
&*self.objc,
|
||||||
relativeToURL:nil
|
bookmarkDataWithOptions: opts,
|
||||||
error:nil
|
includingResourceValuesForKeys: resource_keys,
|
||||||
|
relativeToURL: nil,
|
||||||
|
error: nil,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -158,13 +154,6 @@ impl<'a> NSURL<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*impl From<NSString<'_>> for id {
|
|
||||||
/// Consumes and returns the pointer to the underlying NSString instance.
|
|
||||||
fn from(mut string: NSString) -> Self {
|
|
||||||
&mut *string.objc
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
impl Deref for NSURL<'_> {
|
impl Deref for NSURL<'_> {
|
||||||
type Target = Object;
|
type Target = Object;
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ use crate::foundation::load_or_register_class;
|
||||||
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
|
/// 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_image_view_class() -> *const Class {
|
pub(crate) fn register_image_view_class() -> &'static Class {
|
||||||
load_or_register_class("NSImageView", "RSTImageView", |decl| unsafe {
|
load_or_register_class("NSImageView", "RSTImageView", |decl| unsafe {
|
||||||
//decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
//decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
use objc_id::ShareId;
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
|
|
||||||
/// Views get passed these, and can
|
/// Views get passed these, and can
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ViewHandle<T> {
|
pub struct ViewHandle<T> {
|
||||||
/// A pointer to the Objective-C runtime view controller.
|
/// A pointer to the Objective-C runtime view controller.
|
||||||
pub objc: ShareId<Object>,
|
pub objc: Id<Object, Shared>,
|
||||||
|
|
||||||
_t: std::marker::PhantomData<T>
|
_t: std::marker::PhantomData<T>
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ where
|
||||||
T:
|
T:
|
||||||
|
|
||||||
impl<T> Layout for ViewHandle<T> {
|
impl<T> Layout for ViewHandle<T> {
|
||||||
fn get_backing_node(&self) -> ShareId<Object> {
|
fn get_backing_node(&self) -> Id<Object, Shared> {
|
||||||
self.objc.clone()
|
self.objc.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use objc::runtime::{Class, Object};
|
use objc::rc::{Id, Shared};
|
||||||
use objc_id::ShareId;
|
use objc::runtime::{Bool, Class, Object};
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use core_graphics::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::icons::*;
|
use super::icons::*;
|
||||||
use crate::foundation::{id, NSData, NSString, NO, NSURL, YES};
|
use crate::foundation::{id, NSData, NSString, NSURL};
|
||||||
use crate::utils::os;
|
use crate::utils::os;
|
||||||
|
|
||||||
/// Specifies resizing behavior for image drawing.
|
/// Specifies resizing behavior for image drawing.
|
||||||
|
@ -119,7 +119,7 @@ pub struct DrawConfig {
|
||||||
/// Wraps `NSImage` under AppKit, and `UIImage` on under UIKit (iOS and tvOS). Can be used to display images, icons,
|
/// Wraps `NSImage` under AppKit, and `UIImage` on under UIKit (iOS and tvOS). Can be used to display images, icons,
|
||||||
/// and so on.
|
/// and so on.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Image(pub ShareId<Object>);
|
pub struct Image(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
fn class() -> &'static Class {
|
fn class() -> &'static Class {
|
||||||
|
@ -133,7 +133,7 @@ impl Image {
|
||||||
|
|
||||||
/// Wraps a system-returned image, e.g from QuickLook previews.
|
/// Wraps a system-returned image, e.g from QuickLook previews.
|
||||||
pub fn with(image: id) -> Self {
|
pub fn with(image: id) -> Self {
|
||||||
Image(unsafe { ShareId::from_ptr(image) })
|
Image(unsafe { Id::retain(image).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads an image from the specified path.
|
/// Loads an image from the specified path.
|
||||||
|
@ -141,16 +141,16 @@ impl Image {
|
||||||
let file_path = NSString::new(path);
|
let file_path = NSString::new(path);
|
||||||
|
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
let alloc: id = msg_send![Self::class(), alloc];
|
let alloc = msg_send_id![Self::class(), alloc];
|
||||||
ShareId::from_ptr(msg_send![alloc, initWithContentsOfFile: file_path])
|
msg_send_id![alloc, initWithContentsOfFile: &*file_path]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub fn with_contents_of_url(url: NSURL) -> Self {
|
pub fn with_contents_of_url(url: NSURL) -> Self {
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
let alloc: id = msg_send![Self::class(), alloc];
|
let alloc = msg_send_id![Self::class(), alloc];
|
||||||
ShareId::from_ptr(msg_send![alloc, initWithContentsOfURL: url.objc])
|
msg_send_id![alloc, initWithContentsOfURL: &*url.objc]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +160,8 @@ impl Image {
|
||||||
let data = NSData::with_slice(data);
|
let data = NSData::with_slice(data);
|
||||||
|
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
let alloc: id = msg_send![Self::class(), alloc];
|
let alloc = msg_send_id![Self::class(), alloc];
|
||||||
ShareId::from_ptr(msg_send![alloc, initWithData: data])
|
msg_send_id![alloc, initWithData: &*data]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,10 +172,8 @@ impl Image {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub fn system_icon(icon: MacSystemIcon) -> Self {
|
pub fn system_icon(icon: MacSystemIcon) -> Self {
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
ShareId::from_ptr({
|
let icon = icon.to_id();
|
||||||
let icon = icon.to_id();
|
msg_send_id![Self::class(), imageNamed: icon]
|
||||||
msg_send![Self::class(), imageNamed: icon]
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,19 +190,22 @@ impl Image {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub fn toolbar_icon(icon: MacSystemIcon, accessibility_description: &str) -> Self {
|
pub fn toolbar_icon(icon: MacSystemIcon, accessibility_description: &str) -> Self {
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
ShareId::from_ptr(match os::is_minimum_version(11) {
|
match os::is_minimum_version(11) {
|
||||||
true => {
|
true => {
|
||||||
let icon = NSString::new(icon.to_sfsymbol_str());
|
let icon = NSString::new(icon.to_sfsymbol_str());
|
||||||
let desc = NSString::new(accessibility_description);
|
let desc = NSString::new(accessibility_description);
|
||||||
msg_send![Self::class(), imageWithSystemSymbolName:&*icon
|
msg_send_id![
|
||||||
accessibilityDescription:&*desc]
|
Self::class(),
|
||||||
|
imageWithSystemSymbolName: &*icon,
|
||||||
|
accessibilityDescription: &*desc,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
false => {
|
false => {
|
||||||
let icon = icon.to_id();
|
let icon = icon.to_id();
|
||||||
msg_send![Self::class(), imageNamed: icon]
|
msg_send_id![Self::class(), imageNamed: icon]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,12 +227,15 @@ impl Image {
|
||||||
let min_version = 13;
|
let min_version = 13;
|
||||||
|
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
ShareId::from_ptr(match os::is_minimum_version(min_version) {
|
match os::is_minimum_version(min_version) {
|
||||||
true => {
|
true => {
|
||||||
let icon = NSString::new(symbol.to_str());
|
let icon = NSString::new(symbol.to_str());
|
||||||
let desc = NSString::new(accessibility_description);
|
let desc = NSString::new(accessibility_description);
|
||||||
msg_send![Self::class(), imageWithSystemSymbolName:&*icon
|
msg_send_id![
|
||||||
accessibilityDescription:&*desc]
|
Self::class(),
|
||||||
|
imageWithSystemSymbolName:&*icon,
|
||||||
|
accessibilityDescription:&*desc,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
false => {
|
false => {
|
||||||
|
@ -241,7 +245,7 @@ impl Image {
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
panic!("SFSymbols are only supported on macOS 11.0 and up.");
|
panic!("SFSymbols are only supported on macOS 11.0 and up.");
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,20 +280,17 @@ impl Image {
|
||||||
|
|
||||||
let _: () = msg_send![class!(NSGraphicsContext), restoreGraphicsState];
|
let _: () = msg_send![class!(NSGraphicsContext), restoreGraphicsState];
|
||||||
|
|
||||||
match result {
|
Bool::new(result)
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
let block = block.copy();
|
let block = block.copy();
|
||||||
|
|
||||||
Image(unsafe {
|
Image(unsafe {
|
||||||
let img: id = msg_send![Self::class(), imageWithSize:target_frame.size
|
msg_send_id![
|
||||||
flipped:YES
|
Self::class(),
|
||||||
drawingHandler:block
|
imageWithSize: target_frame.size,
|
||||||
];
|
flipped: Bool::YES,
|
||||||
|
drawingHandler: &*block,
|
||||||
ShareId::from_ptr(img)
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
||||||
|
@ -31,7 +33,7 @@ mod icons;
|
||||||
pub use icons::*;
|
pub use icons::*;
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
fn allocate_view(registration_fn: fn() -> &'static Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
let view: id = msg_send![registration_fn(), new];
|
let view: id = msg_send![registration_fn(), new];
|
||||||
|
|
||||||
|
@ -140,7 +142,7 @@ impl ImageView {
|
||||||
#[cfg(feature = "autolayout")]
|
#[cfg(feature = "autolayout")]
|
||||||
center_y: LayoutAnchorY::center(view),
|
center_y: LayoutAnchorY::center(view),
|
||||||
|
|
||||||
layer: Layer::wrap(unsafe { msg_send![view, layer] }),
|
layer: Layer::from_id(unsafe { msg_send_id![view, layer] }),
|
||||||
|
|
||||||
objc: ObjcProperty::retain(view)
|
objc: ObjcProperty::retain(view)
|
||||||
}
|
}
|
||||||
|
@ -149,7 +151,7 @@ impl ImageView {
|
||||||
/// 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<C: AsRef<Color>>(&self, color: C) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let cg = color.as_ref().cg_color();
|
let cg = color.as_ref().cg_color().as_concrete_TypeRef();
|
||||||
let layer: id = msg_send![obj, layer];
|
let layer: id = msg_send![obj, layer];
|
||||||
let _: () = msg_send![layer, setBackgroundColor: cg];
|
let _: () = msg_send![layer, setBackgroundColor: cg];
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,6 @@ use crate::foundation::load_or_register_class;
|
||||||
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
|
/// 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_image_view_class() -> *const Class {
|
pub(crate) fn register_image_view_class() -> &'static Class {
|
||||||
load_or_register_class("UIImageView", "RSTImageView", |decl| unsafe {})
|
load_or_register_class("UIImageView", "RSTImageView", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +1,71 @@
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::rc::{Id, Owned};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
|
use objc::{msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class, NSString, NO, YES};
|
use crate::foundation::{id, load_or_register_class, NSString};
|
||||||
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
|
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
|
||||||
/// Called when editing this text field has ended (e.g. user pressed enter).
|
/// Called when editing this text field has ended (e.g. user pressed enter).
|
||||||
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_end_editing(s.to_str());
|
view.text_did_end_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_begin_editing(s.to_str());
|
view.text_did_begin_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_change(s.to_str());
|
view.text_did_change(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
|
extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) -> Bool {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
|
|
||||||
match view.text_should_begin_editing(s.to_str()) {
|
Bool::new(view.text_should_begin_editing(s.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
|
extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) -> Bool {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
match view.text_should_end_editing(s.to_str()) {
|
Bool::new(view.text_should_end_editing(s.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSTextField` subclass. This is used for the default views that don't use delegates - we
|
/// Injects an `NSTextField` 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
load_or_register_class("NSTextField", "RSTTextInputField", |decl| unsafe {})
|
load_or_register_class("NSTextField", "RSTTextInputField", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSTextField", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSTextField", instance.subclass_name(), |decl| unsafe {
|
||||||
// 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>(TEXTFIELD_DELEGATE_PTR);
|
decl.add_ivar::<usize>(TEXTFIELD_DELEGATE_PTR);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(sel!(textDidEndEditing:), text_did_end_editing::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(textDidEndEditing:),
|
|
||||||
text_did_end_editing::<T> as extern "C" fn(&mut Object, _, _)
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textDidBeginEditing:),
|
sel!(textDidBeginEditing:),
|
||||||
text_did_begin_editing::<T> as extern "C" fn(&mut Object, _, _)
|
text_did_begin_editing::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(sel!(textDidChange:), text_did_change::<T> as extern "C" fn(&mut Object, _, _));
|
decl.add_method(sel!(textDidChange:), text_did_change::<T> as extern "C" fn(_, _, _));
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textShouldBeginEditing:),
|
sel!(textShouldBeginEditing:),
|
||||||
text_should_begin_editing::<T> as extern "C" fn(&mut Object, Sel, id) -> BOOL
|
text_should_begin_editing::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textShouldEndEditing:),
|
sel!(textShouldEndEditing:),
|
||||||
text_should_end_editing::<T> as extern "C" fn(&mut Object, Sel, id) -> BOOL
|
text_should_end_editing::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,11 @@
|
||||||
//!
|
//!
|
||||||
//! For more information on Autolayout, view the module or check out the examples folder.
|
//! For more information on Autolayout, view the module or check out the examples folder.
|
||||||
|
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::control::Control;
|
use crate::control::Control;
|
||||||
|
@ -76,7 +78,7 @@ pub use traits::TextFieldDelegate;
|
||||||
pub(crate) static TEXTFIELD_DELEGATE_PTR: &str = "rstTextFieldDelegatePtr";
|
pub(crate) static TEXTFIELD_DELEGATE_PTR: &str = "rstTextFieldDelegatePtr";
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn common_init(class: *const Class) -> id {
|
fn common_init(class: &Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
let view: id = msg_send![class, new];
|
let view: id = msg_send![class, new];
|
||||||
|
|
||||||
|
@ -306,7 +308,7 @@ impl<T> TextField<T> {
|
||||||
/// 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<C: AsRef<Color>>(&self, color: C) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let cg = color.as_ref().cg_color();
|
let cg = color.as_ref().cg_color().as_concrete_TypeRef();
|
||||||
let layer: id = msg_send![obj, layer];
|
let layer: id = msg_send![obj, layer];
|
||||||
let _: () = msg_send![layer, setBackgroundColor: cg];
|
let _: () = msg_send![layer, setBackgroundColor: cg];
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,71 +1,64 @@
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class, NSString, NSUInteger, NO, YES};
|
use crate::foundation::{id, load_or_register_class, NSString, NSUInteger};
|
||||||
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
|
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
|
||||||
/// Called when editing this text field has ended (e.g. user pressed enter).
|
/// Called when editing this text field has ended (e.g. user pressed enter).
|
||||||
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, text] });
|
let s = NSString::retain(unsafe { msg_send![this, text] });
|
||||||
view.text_did_end_editing(s.to_str());
|
view.text_did_end_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, text] });
|
let s = NSString::retain(unsafe { msg_send![this, text] });
|
||||||
view.text_did_begin_editing(s.to_str());
|
view.text_did_begin_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, text] });
|
let s = NSString::retain(unsafe { msg_send![this, text] });
|
||||||
view.text_did_change(s.to_str());
|
view.text_did_change(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
|
extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) -> Bool {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, text] });
|
let s = NSString::retain(unsafe { msg_send![this, text] });
|
||||||
|
|
||||||
match view.text_should_begin_editing(s.to_str()) {
|
Bool::new(view.text_should_begin_editing(s.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
|
extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &Object, _: Sel, _info: id) -> Bool {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::retain(unsafe { msg_send![this, text] });
|
let s = NSString::retain(unsafe { msg_send![this, text] });
|
||||||
match view.text_should_end_editing(s.to_str()) {
|
Bool::new(view.text_should_end_editing(s.to_str()))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `UITextField` subclass. This is used for the default views that don't use delegates - we
|
/// Injects an `UITextField` 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<&'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
let superclass = class!(UITextField);
|
let superclass = class!(UITextField);
|
||||||
let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap();
|
let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap();
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `UITextField` subclass, with some callback and pointer ivars for what we
|
/// Injects an `UITextField` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("UITextField", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("UITextField", instance.subclass_name(), |decl| unsafe {
|
||||||
// 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.
|
||||||
|
@ -73,23 +66,23 @@ pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance:
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textFieldDidEndEditing:),
|
sel!(textFieldDidEndEditing:),
|
||||||
text_did_end_editing::<T> as extern "C" fn(&mut Object, _, _)
|
text_did_end_editing::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textFieldDidBeginEditing:),
|
sel!(textFieldDidBeginEditing:),
|
||||||
text_did_begin_editing::<T> as extern "C" fn(&mut Object, _, _)
|
text_did_begin_editing::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textFieldDidChangeSelection:),
|
sel!(textFieldDidChangeSelection:),
|
||||||
text_did_change::<T> as extern "C" fn(&mut Object, _, _)
|
text_did_change::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textFieldShouldBeginEditing:),
|
sel!(textFieldShouldBeginEditing:),
|
||||||
text_should_begin_editing::<T> as extern "C" fn(&mut Object, Sel, id) -> BOOL
|
text_should_begin_editing::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(textFieldShouldEndEditing:),
|
sel!(textFieldShouldEndEditing:),
|
||||||
text_should_end_editing::<T> as extern "C" fn(&mut Object, Sel, id) -> BOOL
|
text_should_end_editing::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::runtime::{Class, Object, Sel};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class};
|
use crate::foundation::{id, load_or_register_class};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
@ -46,7 +46,7 @@ impl fmt::Debug for Action {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TargetActionHandler {
|
pub struct TargetActionHandler {
|
||||||
action: Box<Action>,
|
action: Box<Action>,
|
||||||
invoker: ShareId<Object>
|
invoker: Id<Object, Shared>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetActionHandler {
|
impl TargetActionHandler {
|
||||||
|
@ -56,18 +56,16 @@ impl TargetActionHandler {
|
||||||
let ptr = Box::into_raw(block);
|
let ptr = Box::into_raw(block);
|
||||||
|
|
||||||
let invoker = unsafe {
|
let invoker = unsafe {
|
||||||
ShareId::from_ptr({
|
let invoker = msg_send_id![register_invoker_class::<F>(), alloc];
|
||||||
let invoker: id = msg_send![register_invoker_class::<F>(), alloc];
|
let mut invoker: Id<Object, Owned> = msg_send_id![invoker, init];
|
||||||
let invoker: id = msg_send![invoker, init];
|
invoker.set_ivar(ACTION_CALLBACK_PTR, ptr as usize);
|
||||||
(&mut *invoker).set_ivar(ACTION_CALLBACK_PTR, ptr as usize);
|
let _: () = msg_send![control, setAction: sel!(perform:)];
|
||||||
let _: () = msg_send![control, setAction: sel!(perform:)];
|
let _: () = msg_send![control, setTarget: &*invoker];
|
||||||
let _: () = msg_send![control, setTarget: invoker];
|
invoker.into()
|
||||||
invoker
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TargetActionHandler {
|
TargetActionHandler {
|
||||||
invoker: invoker,
|
invoker,
|
||||||
action: unsafe { Box::from_raw(ptr) }
|
action: unsafe { Box::from_raw(ptr) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,9 +89,9 @@ extern "C" fn perform<F: Fn(*const Object) + 'static>(this: &mut Object, _: Sel,
|
||||||
/// The `NSButton` owns this object on instantiation, and will release it
|
/// The `NSButton` owns this object on instantiation, and will release it
|
||||||
/// on drop. We handle the heap copy on the Rust side, so setting the block
|
/// on drop. We handle the heap copy on the Rust side, so setting the block
|
||||||
/// is just an ivar.
|
/// is just an ivar.
|
||||||
pub(crate) fn register_invoker_class<F: Fn(*const Object) + 'static>() -> *const Class {
|
pub(crate) fn register_invoker_class<F: Fn(*const Object) + 'static>() -> &'static Class {
|
||||||
load_or_register_class("NSObject", "RSTTargetActionHandler", |decl| unsafe {
|
load_or_register_class("NSObject", "RSTTargetActionHandler", |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
|
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
|
||||||
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
|
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(_, _, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::rc::{Id, Shared};
|
||||||
|
use objc::runtime::Object;
|
||||||
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::utils::properties::ObjcProperty;
|
use crate::utils::properties::ObjcProperty;
|
||||||
|
@ -35,30 +37,26 @@ use crate::utils::properties::ObjcProperty;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Layer {
|
pub struct Layer {
|
||||||
/// The underlying layer pointer.
|
/// The underlying layer pointer.
|
||||||
pub objc: ObjcProperty
|
pub objc: Id<Object, Shared>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layer {
|
impl Layer {
|
||||||
/// Creates a new `CALayer` and retains it.
|
/// Creates a new `CALayer` and retains it.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Layer {
|
Layer {
|
||||||
objc: ObjcProperty::retain(unsafe { msg_send![class!(CALayer), new] })
|
objc: unsafe { msg_send_id![class!(CALayer), new] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps an existing (already retained) `CALayer`.
|
/// Wraps an existing `CALayer`.
|
||||||
pub fn wrap(layer: id) -> Self {
|
pub fn from_id(objc: Id<Object, Shared>) -> Self {
|
||||||
Layer {
|
Layer { objc }
|
||||||
objc: ObjcProperty::from_retained(layer)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the corner radius (for all four corners).
|
/// Sets the corner radius (for all four corners).
|
||||||
///
|
///
|
||||||
/// Note that for performance sensitive contexts, you might want to apply a mask instead.
|
/// Note that for performance sensitive contexts, you might want to apply a mask instead.
|
||||||
pub fn set_corner_radius(&self, radius: f64) {
|
pub fn set_corner_radius(&self, radius: f64) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
let _: () = unsafe { msg_send![&self.objc, setCornerRadius: radius as CGFloat] };
|
||||||
let _: () = msg_send![obj, setCornerRadius: radius as CGFloat];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
/// A wrapper for an animation proxy object in Cocoa that supports basic animations.
|
/// A wrapper for an animation proxy object in Cocoa that supports basic animations.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LayoutConstraintAnimatorProxy(pub ShareId<Object>);
|
pub struct LayoutConstraintAnimatorProxy(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl LayoutConstraintAnimatorProxy {
|
impl LayoutConstraintAnimatorProxy {
|
||||||
/// Wraps and returns a proxy for animation of layout constraint values.
|
/// Wraps and returns a proxy for animation of layout constraint values.
|
||||||
pub fn new(proxy: id) -> Self {
|
pub fn new(proxy: id) -> Self {
|
||||||
Self(unsafe { ShareId::from_ptr(msg_send![proxy, animator]) })
|
Self(unsafe { msg_send_id![proxy, animator] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the constant (usually referred to as `offset` in Cacao) value for the constraint being animated.
|
/// Sets the constant (usually referred to as `offset` in Cacao) value for the constraint being animated.
|
||||||
|
@ -23,3 +23,7 @@ impl LayoutConstraintAnimatorProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Safety
|
||||||
|
unsafe impl Send for LayoutConstraintAnimatorProxy {}
|
||||||
|
unsafe impl Sync for LayoutConstraintAnimatorProxy {}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NO, YES};
|
use crate::foundation::{id, NO, YES};
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ use super::LayoutConstraintAnimatorProxy;
|
||||||
pub struct LayoutConstraint {
|
pub struct LayoutConstraint {
|
||||||
/// A shared pointer to the underlying view. Provided your view isn't dropped, this will always
|
/// A shared pointer to the underlying view. Provided your view isn't dropped, this will always
|
||||||
/// be valid.
|
/// be valid.
|
||||||
pub constraint: ShareId<Object>,
|
pub constraint: Id<Object, Shared>,
|
||||||
|
|
||||||
/// The offset used in computing this constraint.
|
/// The offset used in computing this constraint.
|
||||||
pub offset: f64,
|
pub offset: f64,
|
||||||
|
@ -43,8 +43,7 @@ impl LayoutConstraint {
|
||||||
LayoutConstraint {
|
LayoutConstraint {
|
||||||
#[cfg(all(feature = "appkit", target_os = "macos"))]
|
#[cfg(all(feature = "appkit", target_os = "macos"))]
|
||||||
animator: LayoutConstraintAnimatorProxy::new(object),
|
animator: LayoutConstraintAnimatorProxy::new(object),
|
||||||
|
constraint: unsafe { Id::retain(object).unwrap() },
|
||||||
constraint: unsafe { ShareId::from_ptr(object) },
|
|
||||||
offset: 0.0,
|
offset: 0.0,
|
||||||
multiplier: 0.0,
|
multiplier: 0.0,
|
||||||
priority: 0.0
|
priority: 0.0
|
||||||
|
@ -94,7 +93,7 @@ impl LayoutConstraint {
|
||||||
|
|
||||||
/// Call this with your batch of constraints to activate them.
|
/// 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
|
// 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
|
// borrowing rules with how objc::rc::{Id, Owned}/objc::rc::{Id, Shared} works. In this case, to
|
||||||
// support the way autolayout constraints work over in the cocoa runtime, we need to be
|
// 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
|
// able to clone these and pass them around... while also getting certain references to
|
||||||
// them.
|
// them.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSInteger};
|
use crate::foundation::{id, nil, NSInteger};
|
||||||
use crate::layout::constraint::LayoutConstraint;
|
use crate::layout::constraint::LayoutConstraint;
|
||||||
|
@ -12,7 +12,7 @@ use super::attributes::{LayoutAttribute, LayoutRelation};
|
||||||
/// A wrapper for `NSLayoutAnchor`. You should never be creating this yourself - it's more of a
|
/// 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.
|
/// factory/helper for creating `LayoutConstraint` objects based on your views.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct LayoutAnchorDimension2(pub Option<ShareId<Object>>);
|
pub struct LayoutAnchorDimension2(pub Option<Id<Object, Shared>>);
|
||||||
|
|
||||||
/// A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height`
|
/// A wrapper for `NSLayoutAnchorDimension`, which is typically used to handle `width` and `height`
|
||||||
/// values for how a given view should layout.
|
/// values for how a given view should layout.
|
||||||
|
@ -22,10 +22,10 @@ pub enum LayoutAnchorDimension {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
|
||||||
/// Represents a Width anchor.
|
/// Represents a Width anchor.
|
||||||
Width(ShareId<Object>),
|
Width(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a Height anchor.
|
/// Represents a Height anchor.
|
||||||
Height(ShareId<Object>)
|
Height(Id<Object, Shared>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LayoutAnchorDimension {
|
impl Default for LayoutAnchorDimension {
|
||||||
|
@ -38,12 +38,12 @@ impl Default for LayoutAnchorDimension {
|
||||||
impl LayoutAnchorDimension {
|
impl LayoutAnchorDimension {
|
||||||
/// Given a view, returns an anchor for the width anchor.
|
/// Given a view, returns an anchor for the width anchor.
|
||||||
pub(crate) fn width(view: id) -> Self {
|
pub(crate) fn width(view: id) -> Self {
|
||||||
Self::Width(unsafe { ShareId::from_ptr(msg_send![view, widthAnchor]) })
|
Self::Width(unsafe { msg_send_id![view, widthAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the height anchor.
|
/// Given a view, returns an anchor for the height anchor.
|
||||||
pub(crate) fn height(view: id) -> Self {
|
pub(crate) fn height(view: id) -> Self {
|
||||||
Self::Height(unsafe { ShareId::from_ptr(msg_send![view, heightAnchor]) })
|
Self::Height(unsafe { msg_send_id![view, heightAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint equal to a constant value.
|
/// Return a constraint equal to a constant value.
|
||||||
|
@ -51,7 +51,7 @@ impl LayoutAnchorDimension {
|
||||||
if let Self::Width(obj) | Self::Height(obj) = self {
|
if let Self::Width(obj) | Self::Height(obj) = self {
|
||||||
return LayoutConstraint::new(unsafe {
|
return LayoutConstraint::new(unsafe {
|
||||||
let value = constant as CGFloat;
|
let value = constant as CGFloat;
|
||||||
msg_send![*obj, constraintEqualToConstant: value]
|
msg_send![obj, constraintEqualToConstant: value]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ impl LayoutAnchorDimension {
|
||||||
if let Self::Width(obj) | Self::Height(obj) = self {
|
if let Self::Width(obj) | Self::Height(obj) = self {
|
||||||
return LayoutConstraint::new(unsafe {
|
return LayoutConstraint::new(unsafe {
|
||||||
let value = constant as CGFloat;
|
let value = constant as CGFloat;
|
||||||
msg_send![*obj, constraintGreaterThanOrEqualToConstant: value]
|
msg_send![obj, constraintGreaterThanOrEqualToConstant: value]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl LayoutAnchorDimension {
|
||||||
if let Self::Width(obj) | Self::Height(obj) = self {
|
if let Self::Width(obj) | Self::Height(obj) = self {
|
||||||
return LayoutConstraint::new(unsafe {
|
return LayoutConstraint::new(unsafe {
|
||||||
let value = constant as CGFloat;
|
let value = constant as CGFloat;
|
||||||
msg_send![*obj, constraintLessThanOrEqualToConstant: value]
|
msg_send![obj, constraintLessThanOrEqualToConstant: value]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ impl LayoutAnchorDimension {
|
||||||
/// wrong.
|
/// wrong.
|
||||||
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorDimension, handler: F) -> LayoutConstraint
|
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorDimension, handler: F) -> LayoutConstraint
|
||||||
where
|
where
|
||||||
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
|
F: Fn(&Id<Object, Shared>, &Id<Object, Shared>) -> id
|
||||||
{
|
{
|
||||||
match (self, anchor_to) {
|
match (self, anchor_to) {
|
||||||
(Self::Width(from), Self::Width(to))
|
(Self::Width(from), Self::Width(to))
|
||||||
|
@ -112,21 +112,21 @@ impl LayoutAnchorDimension {
|
||||||
/// Return a constraint equal to another dimension anchor.
|
/// Return a constraint equal to another dimension anchor.
|
||||||
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
|
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintEqualToAnchor:&**to]
|
msg_send![from, constraintEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint greater than or equal to another dimension 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 {
|
pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintGreaterThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintGreaterThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint less than or equal to another dimension 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 {
|
pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorDimension) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintLessThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintLessThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::layout::constraint::LayoutConstraint;
|
use crate::layout::constraint::LayoutConstraint;
|
||||||
|
@ -16,19 +16,19 @@ pub enum LayoutAnchorX {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
|
||||||
/// Represents a leading anchor; side depends on system orientation.
|
/// Represents a leading anchor; side depends on system orientation.
|
||||||
Leading(ShareId<Object>),
|
Leading(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a left anchor.
|
/// Represents a left anchor.
|
||||||
Left(ShareId<Object>),
|
Left(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a trailing anchor; side depends on system orientation.
|
/// Represents a trailing anchor; side depends on system orientation.
|
||||||
Trailing(ShareId<Object>),
|
Trailing(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a right anchor.
|
/// Represents a right anchor.
|
||||||
Right(ShareId<Object>),
|
Right(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a center anchor on the X axis.
|
/// Represents a center anchor on the X axis.
|
||||||
Center(ShareId<Object>)
|
Center(Id<Object, Shared>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LayoutAnchorX {
|
impl Default for LayoutAnchorX {
|
||||||
|
@ -41,27 +41,27 @@ impl Default for LayoutAnchorX {
|
||||||
impl LayoutAnchorX {
|
impl LayoutAnchorX {
|
||||||
/// Given a view, returns an anchor for the leading anchor.
|
/// Given a view, returns an anchor for the leading anchor.
|
||||||
pub(crate) fn leading(view: id) -> Self {
|
pub(crate) fn leading(view: id) -> Self {
|
||||||
Self::Leading(unsafe { ShareId::from_ptr(msg_send![view, leadingAnchor]) })
|
Self::Leading(unsafe { msg_send_id![view, leadingAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the left anchor.
|
/// Given a view, returns an anchor for the left anchor.
|
||||||
pub(crate) fn left(view: id) -> Self {
|
pub(crate) fn left(view: id) -> Self {
|
||||||
Self::Left(unsafe { ShareId::from_ptr(msg_send![view, leftAnchor]) })
|
Self::Left(unsafe { msg_send_id![view, leftAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the trailing anchor.
|
/// Given a view, returns an anchor for the trailing anchor.
|
||||||
pub(crate) fn trailing(view: id) -> Self {
|
pub(crate) fn trailing(view: id) -> Self {
|
||||||
Self::Trailing(unsafe { ShareId::from_ptr(msg_send![view, trailingAnchor]) })
|
Self::Trailing(unsafe { msg_send_id![view, trailingAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the right anchor.
|
/// Given a view, returns an anchor for the right anchor.
|
||||||
pub(crate) fn right(view: id) -> Self {
|
pub(crate) fn right(view: id) -> Self {
|
||||||
Self::Right(unsafe { ShareId::from_ptr(msg_send![view, rightAnchor]) })
|
Self::Right(unsafe { msg_send_id![view, rightAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the right anchor.
|
/// Given a view, returns an anchor for the right anchor.
|
||||||
pub(crate) fn center(view: id) -> Self {
|
pub(crate) fn center(view: id) -> Self {
|
||||||
Self::Center(unsafe { ShareId::from_ptr(msg_send![view, centerXAnchor]) })
|
Self::Center(unsafe { msg_send_id![view, centerXAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boilerplate for handling constraint construction and panic'ing with some more helpful
|
/// Boilerplate for handling constraint construction and panic'ing with some more helpful
|
||||||
|
@ -69,7 +69,7 @@ impl LayoutAnchorX {
|
||||||
/// wrong.
|
/// wrong.
|
||||||
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorX, handler: F) -> LayoutConstraint
|
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorX, handler: F) -> LayoutConstraint
|
||||||
where
|
where
|
||||||
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
|
F: Fn(&Id<Object, Shared>, &Id<Object, Shared>) -> id
|
||||||
{
|
{
|
||||||
match (self, anchor_to) {
|
match (self, anchor_to) {
|
||||||
// The anchors that can connect to each other. These blocks could be condensed, but are
|
// The anchors that can connect to each other. These blocks could be condensed, but are
|
||||||
|
@ -160,21 +160,21 @@ impl LayoutAnchorX {
|
||||||
/// Return a constraint equal to another horizontal anchor.
|
/// Return a constraint equal to another horizontal anchor.
|
||||||
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint {
|
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintEqualToAnchor:&**to]
|
msg_send![from, constraintEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint greater than or equal to another horizontal 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 {
|
pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintGreaterThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintGreaterThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint less than or equal to another horizontal 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 {
|
pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorX) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintLessThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintLessThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
|
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
use core_graphics::geometry::{CGPoint, CGRect, CGSize};
|
use core_graphics::geometry::{CGPoint, CGRect, CGSize};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, to_bool, NSArray, NSString, NO, YES};
|
use crate::foundation::{id, nil, to_bool, NSArray, NSString, NO, YES};
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
|
@ -112,7 +112,8 @@ pub trait Layout: ObjcAccess {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let x: NSString = (*t).into();
|
let x: NSString = (*t).into();
|
||||||
x.into()
|
// FIXME: We shouldn't use autorelease here
|
||||||
|
Id::autorelease_return(x.objc)
|
||||||
})
|
})
|
||||||
.collect::<Vec<id>>()
|
.collect::<Vec<id>>()
|
||||||
.into();
|
.into();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::layout::constraint::LayoutConstraint;
|
use crate::layout::constraint::LayoutConstraint;
|
||||||
|
@ -13,13 +13,13 @@ pub enum LayoutAnchorY {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
|
||||||
/// Represents a top anchor.
|
/// Represents a top anchor.
|
||||||
Top(ShareId<Object>),
|
Top(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a bottom anchor.
|
/// Represents a bottom anchor.
|
||||||
Bottom(ShareId<Object>),
|
Bottom(Id<Object, Shared>),
|
||||||
|
|
||||||
/// Represents a center anchor for the Y axis.
|
/// Represents a center anchor for the Y axis.
|
||||||
Center(ShareId<Object>)
|
Center(Id<Object, Shared>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LayoutAnchorY {
|
impl Default for LayoutAnchorY {
|
||||||
|
@ -31,17 +31,17 @@ impl Default for LayoutAnchorY {
|
||||||
impl LayoutAnchorY {
|
impl LayoutAnchorY {
|
||||||
/// Given a view, returns an anchor for the top anchor.
|
/// Given a view, returns an anchor for the top anchor.
|
||||||
pub(crate) fn top(view: id) -> Self {
|
pub(crate) fn top(view: id) -> Self {
|
||||||
Self::Top(unsafe { ShareId::from_ptr(msg_send![view, topAnchor]) })
|
Self::Top(unsafe { msg_send_id![view, topAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the bottom anchor.
|
/// Given a view, returns an anchor for the bottom anchor.
|
||||||
pub(crate) fn bottom(view: id) -> Self {
|
pub(crate) fn bottom(view: id) -> Self {
|
||||||
Self::Bottom(unsafe { ShareId::from_ptr(msg_send![view, bottomAnchor]) })
|
Self::Bottom(unsafe { msg_send_id![view, bottomAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a view, returns an anchor for the center Y anchor.
|
/// Given a view, returns an anchor for the center Y anchor.
|
||||||
pub(crate) fn center(view: id) -> Self {
|
pub(crate) fn center(view: id) -> Self {
|
||||||
Self::Center(unsafe { ShareId::from_ptr(msg_send![view, centerYAnchor]) })
|
Self::Center(unsafe { msg_send_id![view, centerYAnchor] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boilerplate for handling constraint construction and panic'ing with some more helpful
|
/// Boilerplate for handling constraint construction and panic'ing with some more helpful
|
||||||
|
@ -49,7 +49,7 @@ impl LayoutAnchorY {
|
||||||
/// wrong.
|
/// wrong.
|
||||||
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorY, handler: F) -> LayoutConstraint
|
fn constraint_with<F>(&self, anchor_to: &LayoutAnchorY, handler: F) -> LayoutConstraint
|
||||||
where
|
where
|
||||||
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
|
F: Fn(&Id<Object, Shared>, &Id<Object, Shared>) -> id
|
||||||
{
|
{
|
||||||
match (self, anchor_to) {
|
match (self, anchor_to) {
|
||||||
(Self::Top(from), Self::Top(to))
|
(Self::Top(from), Self::Top(to))
|
||||||
|
@ -79,21 +79,21 @@ impl LayoutAnchorY {
|
||||||
/// Return a constraint equal to another vertical anchor.
|
/// Return a constraint equal to another vertical anchor.
|
||||||
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint {
|
pub fn constraint_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintEqualToAnchor:&**to]
|
msg_send![from, constraintEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint greater than or equal to another vertical 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 {
|
pub fn constraint_greater_than_or_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintGreaterThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintGreaterThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a constraint less than or equal to another vertical 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 {
|
pub fn constraint_less_than_or_equal_to(&self, anchor_to: &LayoutAnchorY) -> LayoutConstraint {
|
||||||
self.constraint_with(anchor_to, |from, to| unsafe {
|
self.constraint_with(anchor_to, |from, to| unsafe {
|
||||||
msg_send![*from, constraintLessThanOrEqualToAnchor:&**to]
|
msg_send![from, constraintLessThanOrEqualToAnchor:&**to]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#![cfg_attr(debug_assertions, allow(dead_code, unused_imports))]
|
#![cfg_attr(debug_assertions, allow(dead_code, unused_imports))]
|
||||||
#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
|
#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
// Temporary!
|
||||||
|
#![allow(deprecated)]
|
||||||
// Copyright 2019+, the Cacao developers.
|
// Copyright 2019+, the Cacao developers.
|
||||||
// See the COPYRIGHT file at the top-level directory of this distribution.
|
// See the COPYRIGHT file at the top-level directory of this distribution.
|
||||||
// Dual-licensed under an MIT/MPL-2.0 license, see the LICENSE files in this repository.
|
// Dual-licensed under an MIT/MPL-2.0 license, see the LICENSE files in this repository.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl From<RowActionStyle> for NSUInteger {
|
||||||
/// on a ListViewRow. You return this from the appropriate delegate method,
|
/// on a ListViewRow. You return this from the appropriate delegate method,
|
||||||
/// and the system will handle displaying the necessary pieces for you.
|
/// and the system will handle displaying the necessary pieces for you.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RowAction(pub Id<Object>);
|
pub struct RowAction(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl RowAction {
|
impl RowAction {
|
||||||
/// Creates and returns a new `RowAction`. You'd use this handler to
|
/// Creates and returns a new `RowAction`. You'd use this handler to
|
||||||
|
@ -56,7 +56,7 @@ impl RowAction {
|
||||||
{
|
{
|
||||||
let title = NSString::new(title);
|
let title = NSString::new(title);
|
||||||
let block = ConcreteBlock::new(move |action: id, row: NSUInteger| {
|
let block = ConcreteBlock::new(move |action: id, row: NSUInteger| {
|
||||||
let action = RowAction(unsafe { Id::from_ptr(action) });
|
let action = RowAction(unsafe { Id::retain(action).unwrap() });
|
||||||
|
|
||||||
handler(action, row as usize);
|
handler(action, row as usize);
|
||||||
});
|
});
|
||||||
|
@ -65,10 +65,12 @@ impl RowAction {
|
||||||
|
|
||||||
RowAction(unsafe {
|
RowAction(unsafe {
|
||||||
let cls = class!(NSTableViewRowAction);
|
let cls = class!(NSTableViewRowAction);
|
||||||
Id::from_ptr(msg_send![cls, rowActionWithStyle:style
|
msg_send_id![
|
||||||
title:&*title
|
cls,
|
||||||
handler:block
|
rowActionWithStyle: style,
|
||||||
])
|
title: &*title,
|
||||||
|
handler: &*block,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
//! for in the modern era. It also implements a few helpers for things like setting a background
|
//! for in the modern era. It also implements a few helpers for things like setting a background
|
||||||
//! color, and enforcing layer backing by default.
|
//! color, and enforcing layer backing by default.
|
||||||
|
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::rc::{Id, Owned};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc_id::Id;
|
use objc::{msg_send, sel};
|
||||||
|
|
||||||
use crate::appkit::menu::Menu;
|
use crate::appkit::menu::Menu;
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::foundation::{id, load_or_register_class, NSArray, NSInteger, NSUInteger, NO, YES};
|
use crate::foundation::{id, load_or_register_class, NSArray, NSInteger, NSUInteger};
|
||||||
use crate::listview::{ListViewDelegate, RowEdge, LISTVIEW_DELEGATE_PTR};
|
use crate::listview::{ListViewDelegate, RowEdge, LISTVIEW_DELEGATE_PTR};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
|
|
||||||
|
@ -81,10 +81,10 @@ extern "C" fn select_row<T: ListViewDelegate>(
|
||||||
_: Sel,
|
_: Sel,
|
||||||
_table_view: id,
|
_table_view: id,
|
||||||
item: NSInteger
|
item: NSInteger
|
||||||
) -> BOOL {
|
) -> Bool {
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
view.item_selected(item as usize);
|
view.item_selected(item as usize);
|
||||||
YES
|
Bool::YES
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
extern "C" fn selection_did_change<T: ListViewDelegate>(this: &Object, _: Sel, notification: id) {
|
extern "C" fn selection_did_change<T: ListViewDelegate>(this: &Object, _: Sel, notification: id) {
|
||||||
|
@ -122,41 +122,35 @@ extern "C" fn row_actions_for_row<T: ListViewDelegate>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn dragging_entered<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
extern "C" fn dragging_entered<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
view.dragging_entered(DragInfo {
|
view.dragging_entered(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn prepare_for_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.prepare_for_drag_operation(DragInfo {
|
Bool::new(view.prepare_for_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn perform_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn perform_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.perform_drag_operation(DragInfo {
|
Bool::new(view.perform_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
|
@ -164,7 +158,7 @@ extern "C" fn conclude_drag_operation<T: ListViewDelegate>(this: &mut Object, _:
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.conclude_drag_operation(DragInfo {
|
view.conclude_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +167,7 @@ extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, in
|
||||||
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.dragging_exited(DragInfo {
|
view.dragging_exited(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +175,7 @@ extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, in
|
||||||
/// need to do. Note that we treat and constrain this as a one-column "list" view to match
|
/// need to do. Note that we treat and constrain this as a one-column "list" view to match
|
||||||
/// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can
|
/// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can
|
||||||
/// be added in.
|
/// be added in.
|
||||||
pub(crate) fn register_listview_class() -> *const Class {
|
pub(crate) fn register_listview_class() -> &'static Class {
|
||||||
load_or_register_class("NSTableView", "RSTListView", |decl| unsafe {})
|
load_or_register_class("NSTableView", "RSTListView", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,62 +183,53 @@ pub(crate) fn register_listview_class() -> *const Class {
|
||||||
/// need to do. Note that we treat and constrain this as a one-column "list" view to match
|
/// need to do. Note that we treat and constrain this as a one-column "list" view to match
|
||||||
/// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can
|
/// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can
|
||||||
/// be added in.
|
/// be added in.
|
||||||
pub(crate) fn register_listview_class_with_delegate<T: ListViewDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_listview_class_with_delegate<T: ListViewDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSTableView", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSTableView", instance.subclass_name(), |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(LISTVIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(LISTVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
// Tableview-specific
|
// Tableview-specific
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(numberOfRowsInTableView:),
|
sel!(numberOfRowsInTableView:),
|
||||||
number_of_items::<T> as extern "C" fn(&Object, _, id) -> NSInteger
|
number_of_items::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(tableView:willDisplayCell:forTableColumn:row:),
|
sel!(tableView:willDisplayCell:forTableColumn:row:),
|
||||||
will_display_cell::<T> as extern "C" fn(&Object, _, id, id, id, NSInteger)
|
will_display_cell::<T> as extern "C" fn(_, _, _, _, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(tableView:viewForTableColumn:row:),
|
sel!(tableView:viewForTableColumn:row:),
|
||||||
view_for_column::<T> as extern "C" fn(&Object, _, id, id, NSInteger) -> id
|
view_for_column::<T> as extern "C" fn(_, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(tableViewSelectionDidChange:),
|
sel!(tableViewSelectionDidChange:),
|
||||||
selection_did_change::<T> as extern "C" fn(&Object, _, id)
|
selection_did_change::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(tableView:rowActionsForRow:edge:),
|
sel!(tableView:rowActionsForRow:edge:),
|
||||||
row_actions_for_row::<T> as extern "C" fn(&Object, _, id, NSInteger, NSInteger) -> id
|
row_actions_for_row::<T> as extern "C" fn(_, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// A slot for some menu handling; we just let it be done here for now rather than do the
|
// A slot for some menu handling; we just let it be done here for now rather than do the
|
||||||
// whole delegate run, since things are fast enough nowadays to just replace the entire
|
// whole delegate run, since things are fast enough nowadays to just replace the entire
|
||||||
// menu.
|
// menu.
|
||||||
decl.add_method(
|
decl.add_method(sel!(menuNeedsUpdate:), menu_needs_update::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(menuNeedsUpdate:),
|
|
||||||
menu_needs_update::<T> as extern "C" fn(&Object, _, id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Drag and drop operations (e.g, accepting files)
|
// Drag and drop operations (e.g, accepting files)
|
||||||
decl.add_method(
|
decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(draggingEntered:),
|
|
||||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
prepare_for_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
perform_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
conclude_drag_operation::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(draggingExited:),
|
|
||||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
|
||||||
);
|
);
|
||||||
|
decl.add_method(sel!(draggingExited:), dragging_exited::<T> as extern "C" fn(_, _, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,12 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES};
|
||||||
|
@ -98,7 +100,7 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn common_init(class: *const Class) -> id {
|
fn common_init(class: &Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Note: we do *not* enable AutoLayout here as we're by default placing this in a scroll
|
// Note: we do *not* enable AutoLayout here as we're by default placing this in a scroll
|
||||||
// view, and we want it to just do its thing.
|
// view, and we want it to just do its thing.
|
||||||
|
@ -439,7 +441,7 @@ impl<T> ListView<T> {
|
||||||
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
// @TODO: This is wrong.
|
// @TODO: This is wrong.
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let color = color.as_ref().cg_color();
|
let color = color.as_ref().cg_color().as_concrete_TypeRef();
|
||||||
let layer: id = msg_send![obj, layer];
|
let layer: id = msg_send![obj, layer];
|
||||||
let _: () = msg_send![layer, setBackgroundColor: color];
|
let _: () = msg_send![layer, setBackgroundColor: color];
|
||||||
});
|
});
|
||||||
|
@ -484,14 +486,14 @@ impl<T> ListView<T> {
|
||||||
/// Select the rows at the specified indexes, optionally adding to any existing selections.
|
/// Select the rows at the specified indexes, optionally adding to any existing selections.
|
||||||
pub fn select_row_indexes(&self, indexes: &[usize], extends_existing: bool) {
|
pub fn select_row_indexes(&self, indexes: &[usize], extends_existing: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
let mut index_set: Id<Object, Owned> = msg_send_id![class!(NSMutableIndexSet), new];
|
||||||
|
|
||||||
for index in indexes {
|
for index in indexes {
|
||||||
let _: () = msg_send![index_set, addIndex: index];
|
let _: () = msg_send![&mut index_set, addIndex: index];
|
||||||
}
|
}
|
||||||
|
|
||||||
self.objc.with_mut(|obj| {
|
self.objc.with_mut(|obj| {
|
||||||
let _: () = msg_send![obj, selectRowIndexes:index_set byExtendingSelection:match extends_existing {
|
let _: () = msg_send![obj, selectRowIndexes: &*index_set, byExtendingSelection: match extends_existing {
|
||||||
true => YES,
|
true => YES,
|
||||||
false => NO
|
false => NO
|
||||||
}];
|
}];
|
||||||
|
@ -567,23 +569,24 @@ impl<T> ListView<T> {
|
||||||
pub fn insert_rows(&self, indexes: &[usize], animation: RowAnimation) {
|
pub fn insert_rows(&self, indexes: &[usize], animation: RowAnimation) {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
let mut index_set: Id<Object, Owned> = msg_send_id![class!(NSMutableIndexSet), new];
|
||||||
|
|
||||||
for index in indexes {
|
for index in indexes {
|
||||||
let x: NSUInteger = *index as NSUInteger;
|
let x: NSUInteger = *index as NSUInteger;
|
||||||
let _: () = msg_send![index_set, addIndex: x];
|
let _: () = msg_send![&mut index_set, addIndex: x];
|
||||||
}
|
}
|
||||||
|
|
||||||
let animation_options: NSUInteger = animation.into();
|
let animation_options: NSUInteger = animation.into();
|
||||||
|
|
||||||
// We need to temporarily retain this; it can drop after the underlying NSTableView
|
// We need to temporarily retain this; it can drop after the underlying NSTableView
|
||||||
// has also retained it.
|
// has also retained it.
|
||||||
let x = ShareId::from_ptr(index_set);
|
let index_set: Id<Object, Shared> = index_set.into();
|
||||||
|
let x = index_set.clone();
|
||||||
|
|
||||||
// This is done for a very explicit reason; see the comments on the method itself for
|
// This is done for a very explicit reason; see the comments on the method itself for
|
||||||
// an explanation.
|
// an explanation.
|
||||||
self.hack_avoid_dequeue_loop(|obj| {
|
self.hack_avoid_dequeue_loop(|obj| {
|
||||||
let _: () = msg_send![obj, insertRowsAtIndexes:&*x withAnimation:animation_options];
|
let _: () = msg_send![obj, insertRowsAtIndexes: &*x, withAnimation: animation_options];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,21 +595,21 @@ impl<T> ListView<T> {
|
||||||
pub fn reload_rows(&self, indexes: &[usize]) {
|
pub fn reload_rows(&self, indexes: &[usize]) {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
let mut index_set: Id<Object, Owned> = msg_send_id![class!(NSMutableIndexSet), new];
|
||||||
|
|
||||||
for index in indexes {
|
for index in indexes {
|
||||||
let x: NSUInteger = *index as NSUInteger;
|
let x: NSUInteger = *index as NSUInteger;
|
||||||
let _: () = msg_send![index_set, addIndex: x];
|
let _: () = msg_send![&mut index_set, addIndex: x];
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = ShareId::from_ptr(index_set);
|
let index_set: Id<Object, Shared> = index_set.into();
|
||||||
|
let x = index_set.clone();
|
||||||
|
|
||||||
let ye: id = msg_send![class!(NSIndexSet), indexSetWithIndex:0];
|
let y: Id<Object, Shared> = msg_send_id![class!(NSIndexSet), indexSetWithIndex:0];
|
||||||
let y = ShareId::from_ptr(ye);
|
|
||||||
|
|
||||||
// Must use `get` to avoid a double lock.
|
// Must use `get` to avoid a double lock.
|
||||||
self.objc.get(|obj| {
|
self.objc.get(|obj| {
|
||||||
let _: () = msg_send![obj, reloadDataForRowIndexes:&*x columnIndexes:&*y];
|
let _: () = msg_send![obj, reloadDataForRowIndexes: &*x, columnIndexes: &*y];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -619,20 +622,22 @@ impl<T> ListView<T> {
|
||||||
pub fn remove_rows(&self, indexes: &[usize], animations: RowAnimation) {
|
pub fn remove_rows(&self, indexes: &[usize], animations: RowAnimation) {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
unsafe {
|
unsafe {
|
||||||
let index_set: id = msg_send![class!(NSMutableIndexSet), new];
|
let mut index_set: Id<Object, Owned> = msg_send_id![class!(NSMutableIndexSet), new];
|
||||||
|
|
||||||
for index in indexes {
|
for index in indexes {
|
||||||
let x: NSUInteger = *index as NSUInteger;
|
let x: NSUInteger = *index as NSUInteger;
|
||||||
let _: () = msg_send![index_set, addIndex: x];
|
let _: () = msg_send![&mut index_set, addIndex: x];
|
||||||
}
|
}
|
||||||
|
|
||||||
let animation_options: NSUInteger = animations.into();
|
let animation_options: NSUInteger = animations.into();
|
||||||
|
|
||||||
// We need to temporarily retain this; it can drop after the underlying NSTableView
|
// We need to temporarily retain this; it can drop after the underlying NSTableView
|
||||||
// has also retained it.
|
// has also retained it.
|
||||||
let x = ShareId::from_ptr(index_set);
|
let index_set: Id<Object, Shared> = index_set.into();
|
||||||
|
let x = index_set.clone();
|
||||||
|
|
||||||
self.objc.with_mut(|obj| {
|
self.objc.with_mut(|obj| {
|
||||||
let _: () = msg_send![obj, removeRowsAtIndexes:&*x withAnimation:animation_options];
|
let _: () = msg_send![obj, removeRowsAtIndexes: &*x, withAnimation: animation_options];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,51 +7,45 @@
|
||||||
//! for in the modern era. It also implements a few helpers for things like setting a background
|
//! for in the modern era. It also implements a few helpers for things like setting a background
|
||||||
//! color, and enforcing layer backing by default.
|
//! color, and enforcing layer backing by default.
|
||||||
|
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::rc::{Id, Owned};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc_id::Id;
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::foundation::{id, load_or_register_class, nil, NSUInteger, NO, YES};
|
use crate::foundation::{id, load_or_register_class, nil, NSUInteger};
|
||||||
use crate::listview::row::{ViewDelegate, BACKGROUND_COLOR, LISTVIEW_ROW_DELEGATE_PTR};
|
use crate::listview::row::{ViewDelegate, BACKGROUND_COLOR, LISTVIEW_ROW_DELEGATE_PTR};
|
||||||
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.
|
||||||
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
extern "C" fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
||||||
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
view.dragging_entered(DragInfo {
|
view.dragging_entered(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn prepare_for_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.prepare_for_drag_operation(DragInfo {
|
Bool::new(view.prepare_for_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn perform_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn perform_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.perform_drag_operation(DragInfo {
|
Bool::new(view.perform_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
|
@ -59,7 +53,7 @@ extern "C" fn conclude_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel
|
||||||
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.conclude_drag_operation(DragInfo {
|
view.conclude_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +62,7 @@ extern "C" fn dragging_exited<T: ViewDelegate>(this: &mut Object, _: Sel, info:
|
||||||
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
let view = load::<T>(this, LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.dragging_exited(DragInfo {
|
view.dragging_exited(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,47 +97,41 @@ extern "C" fn dealloc<T: ViewDelegate>(this: &Object, _: Sel) {
|
||||||
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
|
/// 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_listview_row_class() -> *const Class {
|
pub(crate) fn register_listview_row_class() -> &'static Class {
|
||||||
load_or_register_class("NSView", "RSTTableViewRow", |decl| unsafe {
|
load_or_register_class("NSView", "RSTTableViewRow", |decl| unsafe {
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *const Class {
|
pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> &'static Class {
|
||||||
load_or_register_class("NSView", "RSTableViewRowWithDelegate", |decl| unsafe {
|
load_or_register_class("NSView", "RSTableViewRowWithDelegate", |decl| unsafe {
|
||||||
// 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>(LISTVIEW_ROW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR);
|
||||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||||
|
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(_, _));
|
||||||
|
|
||||||
// Drag and drop operations (e.g, accepting files)
|
// Drag and drop operations (e.g, accepting files)
|
||||||
decl.add_method(
|
decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(draggingEntered:),
|
|
||||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
prepare_for_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
perform_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
conclude_drag_operation::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(draggingExited:),
|
|
||||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
|
||||||
);
|
);
|
||||||
|
decl.add_method(sel!(draggingExited:), dragging_exited::<T> as extern "C" fn(_, _, _));
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _));
|
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(_, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::{Id, ShareId};
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
||||||
|
@ -77,7 +77,7 @@ pub(crate) static BACKGROUND_COLOR: &str = "cacaoBackgroundColor";
|
||||||
pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "cacaoListViewRowDelegatePtr";
|
pub(crate) static LISTVIEW_ROW_DELEGATE_PTR: &str = "cacaoListViewRowDelegatePtr";
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
fn allocate_view(registration_fn: fn() -> &'static Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
let view: id = msg_send![registration_fn(), new];
|
let view: id = msg_send![registration_fn(), new];
|
||||||
|
|
||||||
|
@ -442,7 +442,8 @@ impl<T> ListViewRow<T> {
|
||||||
let color: id = color.as_ref().into();
|
let color: id = color.as_ref().into();
|
||||||
|
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
(&mut *obj).set_ivar(BACKGROUND_COLOR, color);
|
// TODO: Fix this unnecessary retain!
|
||||||
|
(&mut *obj).set_ivar::<id>(BACKGROUND_COLOR, msg_send![color, retain]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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, sel, sel_impl};
|
use objc::{class, sel};
|
||||||
use objc_id::Id;
|
use objc::rc::{Id, Owned};
|
||||||
|
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::foundation::{id, NSUInteger, NO, YES};
|
use crate::foundation::{id, NSUInteger, NO, YES};
|
||||||
|
@ -11,13 +11,13 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
|
||||||
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
|
/// 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
load_or_register_class("UIView", "RSTView", |decl| unsafe {})
|
load_or_register_class("UIView", "RSTView", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> &'static Class {
|
||||||
load_or_register_class("UIView", "RSTViewWithDelegate", |decl| unsafe {
|
load_or_register_class("UIView", "RSTViewWithDelegate", |decl| unsafe {
|
||||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
//! A lightweight wrapper over some networking components, like `NSURLRequest` and co.
|
//! A lightweight wrapper over some networking components, like `NSURLRequest` and co.
|
||||||
//!
|
//!
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
/// At the moment, this is mostly used for inspection of objects returned from system
|
/// At the moment, this is mostly used for inspection of objects returned from system
|
||||||
/// calls, as `NSURL` is pervasive in some filesystem references. Over time this may grow to
|
/// calls, as `NSURL` is pervasive in some filesystem references. Over time this may grow to
|
||||||
/// include a proper networking stack, but the expectation for v0.1 is that most apps will want to
|
/// include a proper networking stack, but the expectation for v0.1 is that most apps will want to
|
||||||
/// use their standard Rust networking libraries (however... odd... the async story may be).
|
/// use their standard Rust networking libraries (however... odd... the async story may be).
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
|
|
||||||
/// A wrapper around `NSURLRequest`.
|
/// A wrapper around `NSURLRequest`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct URLRequest(ShareId<Object>);
|
pub struct URLRequest(Id<Object, Shared>);
|
||||||
|
|
||||||
impl URLRequest {
|
impl URLRequest {
|
||||||
/// Wraps and retains an `NSURLRequest`.
|
/// Wraps and retains an `NSURLRequest`.
|
||||||
pub fn with(request: id) -> Self {
|
pub fn with(request: id) -> Self {
|
||||||
URLRequest(unsafe { ShareId::from_ptr(request) })
|
URLRequest(unsafe { Id::retain(request).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the underlying request URL as an owned `String`.
|
/// Returns the underlying request URL as an owned `String`.
|
||||||
pub fn absolute_url(&self) -> String {
|
pub fn absolute_url(&self) -> String {
|
||||||
NSString::from_retained(unsafe {
|
NSString::retain(unsafe {
|
||||||
let url: id = msg_send![&*self.0, URL];
|
let url: id = msg_send![&*self.0, URL];
|
||||||
msg_send![url, absoluteString]
|
msg_send![url, absoluteString]
|
||||||
})
|
})
|
||||||
|
@ -32,7 +32,7 @@ impl URLRequest {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
use crate::networking::URLRequest;
|
use crate::networking::URLRequest;
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
//use std::collections::HashMap;
|
//use std::collections::HashMap;
|
||||||
|
|
||||||
//use lazy_static::lazy_static;
|
//use lazy_static::lazy_static;
|
||||||
//use objc::{class, msg_send, sel, sel_impl};
|
//use objc::{class, msg_send, msg_send_id, sel};
|
||||||
//use objc::runtime::Object;
|
//use objc::runtime::Object;
|
||||||
//use objc_id::ShareId;
|
//use objc::rc::{Id, Shared};
|
||||||
|
|
||||||
mod name;
|
mod name;
|
||||||
pub use name::NotificationName;
|
pub use name::NotificationName;
|
||||||
|
@ -30,7 +30,7 @@ pub use traits::Dispatcher;
|
||||||
pub static ref DefaultNotificationCenter: NotificationCenter = {
|
pub static ref DefaultNotificationCenter: NotificationCenter = {
|
||||||
NotificationCenter {
|
NotificationCenter {
|
||||||
objc: unsafe {
|
objc: unsafe {
|
||||||
ShareId::from_ptr(msg_send![class!(NSNotificationCenter), defaultCenter])
|
msg_send_id![class!(NSNotificationCenter), defaultCenter]
|
||||||
},
|
},
|
||||||
|
|
||||||
subscribers: Mutex::new(HashMap::new())
|
subscribers: Mutex::new(HashMap::new())
|
||||||
|
@ -42,7 +42,7 @@ pub use traits::Dispatcher;
|
||||||
// default center; in the future it should aim to support custom variants.
|
// default center; in the future it should aim to support custom variants.
|
||||||
//#[derive(Debug)]
|
//#[derive(Debug)]
|
||||||
//pub struct NotificationCenter {
|
//pub struct NotificationCenter {
|
||||||
// pub objc: ShareId<Object>,
|
// pub objc: Id<Object, Shared>,
|
||||||
//pub subscribers: Mutex<HashMap<String, Vec<Dispatcher>>>
|
//pub subscribers: Mutex<HashMap<String, Vec<Dispatcher>>>
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ pub use traits::Dispatcher;
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NotificationCenter {
|
NotificationCenter {
|
||||||
objc: unsafe {
|
objc: unsafe {
|
||||||
ShareId::from_ptr(msg_send![class!(NSNotificationCenter), defaultCenter])
|
msg_send_id![class!(NSNotificationCenter), defaultCenter]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
@ -28,33 +28,33 @@ pub use types::{PasteboardName, PasteboardType};
|
||||||
|
|
||||||
/// Represents an `NSPasteboard`, enabling you to handle copy/paste/drag and drop.
|
/// Represents an `NSPasteboard`, enabling you to handle copy/paste/drag and drop.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Pasteboard(pub ShareId<Object>);
|
pub struct Pasteboard(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl Default for Pasteboard {
|
impl Default for Pasteboard {
|
||||||
/// Returns the default system pasteboard (the "general" pasteboard).
|
/// Returns the default system pasteboard (the "general" pasteboard).
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Pasteboard(unsafe { ShareId::from_ptr(msg_send![class!(NSPasteboard), generalPasteboard]) })
|
Pasteboard(unsafe { msg_send_id![class!(NSPasteboard), generalPasteboard] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pasteboard {
|
impl Pasteboard {
|
||||||
/// Used internally for wrapping a Pasteboard returned from operations (say, drag and drop).
|
/// Used internally for wrapping a Pasteboard returned from operations (say, drag and drop).
|
||||||
pub(crate) fn with(existing: id) -> Self {
|
pub(crate) fn with(existing: id) -> Self {
|
||||||
Pasteboard(unsafe { ShareId::from_ptr(existing) })
|
Pasteboard(unsafe { Id::retain(existing).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the system Pasteboard for the given name/type.
|
/// Retrieves the system Pasteboard for the given name/type.
|
||||||
pub fn named(name: PasteboardName) -> Self {
|
pub fn named(name: PasteboardName) -> Self {
|
||||||
Pasteboard(unsafe {
|
Pasteboard(unsafe {
|
||||||
let name: NSString = name.into();
|
let name: NSString = name.into();
|
||||||
ShareId::from_ptr(msg_send![class!(NSPasteboard), pasteboardWithName:&*name])
|
msg_send_id![class!(NSPasteboard), pasteboardWithName:&*name]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and returns a new pasteboard with a name that is guaranteed to be unique with
|
/// Creates and returns a new pasteboard with a name that is guaranteed to be unique with
|
||||||
/// respect to other pasteboards in the system.
|
/// respect to other pasteboards in the system.
|
||||||
pub fn unique() -> Self {
|
pub fn unique() -> Self {
|
||||||
Pasteboard(unsafe { ShareId::from_ptr(msg_send![class!(NSPasteboard), pasteboardWithUniqueName]) })
|
Pasteboard(unsafe { msg_send_id![class!(NSPasteboard), pasteboardWithUniqueName] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A shorthand helper method for copying some text to the clipboard.
|
/// A shorthand helper method for copying some text to the clipboard.
|
||||||
|
@ -63,7 +63,7 @@ impl Pasteboard {
|
||||||
let ptype: NSString = PasteboardType::String.into();
|
let ptype: NSString = PasteboardType::String.into();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, setString:&*contents forType:ptype];
|
let _: () = msg_send![&*self.0, setString: &*contents, forType: &*ptype];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ impl Pasteboard {
|
||||||
unsafe {
|
unsafe {
|
||||||
let class: id = msg_send![class!(NSURL), class];
|
let class: id = msg_send![class!(NSURL), class];
|
||||||
let classes = NSArray::new(&[class]);
|
let classes = NSArray::new(&[class]);
|
||||||
let contents: id = msg_send![&*self.0, readObjectsForClasses:classes options:nil];
|
let contents: id = msg_send![&*self.0, readObjectsForClasses: &*classes, options: nil];
|
||||||
|
|
||||||
// This can happen if the Pasteboard server has an error in returning items.
|
// This can happen if the Pasteboard server has an error in returning items.
|
||||||
// In our case, we'll bubble up an error by checking the pasteboard.
|
// In our case, we'll bubble up an error by checking the pasteboard.
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, NSUInteger, NO, YES};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString, NSUInteger, YES};
|
use crate::foundation::{id, NSString, NSUInteger, YES};
|
||||||
use crate::utils::CGSize;
|
use crate::utils::CGSize;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@ mod config;
|
||||||
pub use config::{ThumbnailConfig, ThumbnailQuality};
|
pub use config::{ThumbnailConfig, ThumbnailQuality};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ThumbnailGenerator(pub ShareId<Object>);
|
pub struct ThumbnailGenerator(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl ThumbnailGenerator {
|
impl ThumbnailGenerator {
|
||||||
/// Returns the global shared, wrapped, QLThumbnailGenerator.
|
/// Returns the global shared, wrapped, QLThumbnailGenerator.
|
||||||
pub fn shared() -> Self {
|
pub fn shared() -> Self {
|
||||||
ThumbnailGenerator(unsafe { ShareId::from_ptr(msg_send![class!(QLThumbnailGenerator), sharedGenerator]) })
|
ThumbnailGenerator(unsafe { msg_send_id![class!(QLThumbnailGenerator), sharedGenerator] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a path and config, will generate a preview image, calling back on the provided
|
/// Given a path and config, will generate a preview image, calling back on the provided
|
||||||
|
@ -48,8 +48,11 @@ impl ThumbnailGenerator {
|
||||||
let request = config.to_request(path);
|
let request = config.to_request(path);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, generateRepresentationsForRequest:request
|
let _: () = msg_send![
|
||||||
updateHandler:block];
|
&*self.0,
|
||||||
|
generateRepresentationsForRequest: request,
|
||||||
|
updateHandler: &*block,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,51 +7,45 @@
|
||||||
//! for in the modern era. It also implements a few helpers for things like setting a background
|
//! for in the modern era. It also implements a few helpers for things like setting a background
|
||||||
//! color, and enforcing layer backing by default.
|
//! color, and enforcing layer backing by default.
|
||||||
|
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::rc::{Id, Owned};
|
||||||
use objc::{sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc_id::Id;
|
use objc::sel;
|
||||||
|
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::foundation::{id, load_or_register_class, NSUInteger, NO, YES};
|
use crate::foundation::{id, load_or_register_class, NSUInteger};
|
||||||
use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR};
|
use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR};
|
||||||
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.
|
||||||
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn dragging_entered<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
extern "C" fn dragging_entered<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
view.dragging_entered(DragInfo {
|
view.dragging_entered(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn prepare_for_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.prepare_for_drag_operation(DragInfo {
|
Bool::new(view.prepare_for_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn perform_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn perform_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.perform_drag_operation(DragInfo {
|
Bool::new(view.perform_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
|
@ -59,7 +53,7 @@ extern "C" fn conclude_drag_operation<T: ScrollViewDelegate>(this: &mut Object,
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.conclude_drag_operation(DragInfo {
|
view.conclude_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,45 +62,38 @@ extern "C" fn dragging_exited<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.dragging_exited(DragInfo {
|
view.dragging_exited(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSScrollView` subclass.
|
/// Injects an `NSScrollView` subclass.
|
||||||
pub(crate) fn register_scrollview_class() -> *const Class {
|
pub(crate) fn register_scrollview_class() -> &'static Class {
|
||||||
load_or_register_class("NSScrollView", "RSTScrollView", |decl| unsafe {})
|
load_or_register_class("NSScrollView", "RSTScrollView", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class {
|
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> &'static Class {
|
||||||
load_or_register_class("NSScrollView", "RSTScrollViewWithDelegate", |decl| unsafe {
|
load_or_register_class("NSScrollView", "RSTScrollViewWithDelegate", |decl| unsafe {
|
||||||
// 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>(SCROLLVIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
// Drag and drop operations (e.g, accepting files)
|
// Drag and drop operations (e.g, accepting files)
|
||||||
decl.add_method(
|
decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(draggingEntered:),
|
|
||||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
prepare_for_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
perform_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
conclude_drag_operation::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(draggingExited:),
|
|
||||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,11 @@
|
||||||
//!
|
//!
|
||||||
//! For more information on Autolayout, view the module or check out the examples folder.
|
//! For more information on Autolayout, view the module or check out the examples folder.
|
||||||
|
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
||||||
|
@ -73,7 +75,7 @@ pub use traits::ScrollViewDelegate;
|
||||||
pub(crate) static SCROLLVIEW_DELEGATE_PTR: &str = "rstScrollViewDelegatePtr";
|
pub(crate) static SCROLLVIEW_DELEGATE_PTR: &str = "rstScrollViewDelegatePtr";
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
fn allocate_view(registration_fn: fn() -> &'static Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
let view: id = msg_send![registration_fn(), new];
|
let view: id = msg_send![registration_fn(), new];
|
||||||
|
|
||||||
|
@ -296,7 +298,7 @@ impl<T> ScrollView<T> {
|
||||||
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
pub fn set_background_color<C: AsRef<Color>>(&self, color: C) {
|
||||||
// @TODO: This is wrong.
|
// @TODO: This is wrong.
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let color = color.as_ref().cg_color();
|
let color = color.as_ref().cg_color().as_concrete_TypeRef();
|
||||||
let layer: id = msg_send![obj, layer];
|
let layer: id = msg_send![obj, layer];
|
||||||
let _: () = msg_send![layer, setBackgroundColor: color];
|
let _: () = msg_send![layer, setBackgroundColor: color];
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,17 +10,16 @@
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc::{class, sel, sel_impl};
|
use objc::{class, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSUInteger, NO, YES};
|
use crate::foundation::{id, NSUInteger};
|
||||||
use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR};
|
use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR};
|
||||||
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.
|
||||||
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -35,27 +34,21 @@ extern "C" fn dragging_entered<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn prepare_for_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.prepare_for_drag_operation(DragInfo {
|
Bool::new(view.prepare_for_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::from_ptr(info) }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn perform_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn perform_drag_operation<T: ScrollViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
let view = load::<T>(this, SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.perform_drag_operation(DragInfo {
|
Bool::new(view.perform_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::from_ptr(info) }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
|
@ -78,23 +71,23 @@ extern "C" fn dragging_exited<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// Injects an `UIScrollView` subclass.
|
/// Injects an `UIScrollView` subclass.
|
||||||
pub(crate) fn register_scrollview_class() -> *const Class {
|
pub(crate) fn register_scrollview_class() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<&'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
let superclass = class!(UIScrollView);
|
let superclass = class!(UIScrollView);
|
||||||
let decl = ClassDecl::new("RSTScrollView", superclass).unwrap();
|
let decl = ClassDecl::new("RSTScrollView", superclass).unwrap();
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class {
|
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<&'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
|
@ -105,34 +98,34 @@ pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -
|
||||||
// move.
|
// move.
|
||||||
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Drag and drop operations (e.g, accepting files)
|
// Drag and drop operations (e.g, accepting files)
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(draggingEntered:),
|
sel!(draggingEntered:),
|
||||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
dragging_entered::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
prepare_for_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
perform_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
conclude_drag_operation::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(draggingExited:),
|
sel!(draggingExited:),
|
||||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
dragging_exited::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Implements a Select-style dropdown. By default this uses NSPopupSelect on macOS.
|
//! Implements a Select-style dropdown. By default this uses NSPopupSelect on macOS.
|
||||||
|
|
||||||
use core_graphics::geometry::CGRect;
|
use core_graphics::geometry::CGRect;
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::control::Control;
|
use crate::control::Control;
|
||||||
use crate::foundation::{id, load_or_register_class, nil, NSInteger, NSString, NO, YES};
|
use crate::foundation::{id, load_or_register_class, nil, NSInteger, NSString, NO, YES};
|
||||||
|
@ -142,7 +142,7 @@ impl Select {
|
||||||
/// I cannot stress this enough.
|
/// I cannot stress this enough.
|
||||||
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
||||||
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
||||||
let this = self.objc.get(|obj| unsafe { ShareId::from_ptr(msg_send![obj, self]) });
|
let this: Id<Object, Shared> = self.objc.get(|obj| unsafe { msg_send_id![obj, self] });
|
||||||
let handler = TargetActionHandler::new(&*this, action);
|
let handler = TargetActionHandler::new(&*this, action);
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ impl Select {
|
||||||
pub fn add_item(&self, title: &str) {
|
pub fn add_item(&self, title: &str) {
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let s = NSString::new(title);
|
let s = NSString::new(title);
|
||||||
let _: () = msg_send![obj, addItemWithTitle: s];
|
let _: () = msg_send![obj, addItemWithTitle: &*s];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +262,6 @@ impl Drop for Select {
|
||||||
|
|
||||||
/// Registers an `NSSelect` subclass, and configures it to hold some ivars
|
/// Registers an `NSSelect` subclass, and configures it to hold some ivars
|
||||||
/// for various things we need to store.
|
/// for various things we need to store.
|
||||||
fn register_class() -> *const Class {
|
fn register_class() -> &'static Class {
|
||||||
load_or_register_class("NSPopUpButton", "CacaoSelect", |decl| unsafe {})
|
load_or_register_class("NSPopUpButton", "CacaoSelect", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! A wrapper for NSSwitch. Currently the epitome of jank - if you're poking around here, expect
|
//! A wrapper for NSSwitch. Currently the epitome of jank - if you're poking around here, expect
|
||||||
//! that this will change at some point.
|
//! that this will change at some point.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class, nil, NSString, NO};
|
use crate::foundation::{id, load_or_register_class, nil, NSString, NO};
|
||||||
use crate::invoker::TargetActionHandler;
|
use crate::invoker::TargetActionHandler;
|
||||||
|
@ -69,7 +69,7 @@ impl Switch {
|
||||||
let title = NSString::new(text);
|
let title = NSString::new(text);
|
||||||
|
|
||||||
let view: id = unsafe {
|
let view: id = unsafe {
|
||||||
let button: id = msg_send![register_class(), buttonWithTitle:title target:nil action:nil];
|
let button: id = msg_send![register_class(), buttonWithTitle: &*title, target: nil, action: nil];
|
||||||
|
|
||||||
#[cfg(feature = "autolayout")]
|
#[cfg(feature = "autolayout")]
|
||||||
let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints: NO];
|
let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints: NO];
|
||||||
|
@ -132,7 +132,7 @@ impl Switch {
|
||||||
/// best just to message pass or something.
|
/// best just to message pass or something.
|
||||||
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
pub fn set_action<F: Fn(*const Object) + Send + Sync + 'static>(&mut self, action: F) {
|
||||||
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
// @TODO: This probably isn't ideal but gets the job done for now; needs revisiting.
|
||||||
let this = self.objc.get(|obj| unsafe { ShareId::from_ptr(msg_send![obj, self]) });
|
let this: Id<Object, Shared> = self.objc.get(|obj| unsafe { msg_send_id![obj, self] });
|
||||||
let handler = TargetActionHandler::new(&*this, action);
|
let handler = TargetActionHandler::new(&*this, action);
|
||||||
self.handler = Some(handler);
|
self.handler = Some(handler);
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,6 @@ impl Drop for Switch {
|
||||||
|
|
||||||
/// Registers an `NSButton` subclass, and configures it to hold some ivars
|
/// Registers an `NSButton` subclass, and configures it to hold some ivars
|
||||||
/// for various things we need to store.
|
/// for various things we need to store.
|
||||||
fn register_class() -> *const Class {
|
fn register_class() -> &'static Class {
|
||||||
load_or_register_class("NSButton", "RSTSwitch", |decl| unsafe {})
|
load_or_register_class("NSButton", "RSTSwitch", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,13 @@ use std::ops::{Deref, DerefMut, Range};
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::{fmt, slice, str};
|
use std::{fmt, slice, str};
|
||||||
|
|
||||||
use core_foundation::base::CFRange;
|
use objc::rc::{Id, Owned};
|
||||||
|
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, to_bool, NSString, BOOL, NO, YES};
|
use crate::foundation::{id, to_bool, NSString, BOOL, NO, YES};
|
||||||
|
use crate::utils::CFRange;
|
||||||
|
|
||||||
use super::Font;
|
use super::Font;
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ extern "C" {
|
||||||
/// A wrapper around `NSMutableAttributedString`, which can be used for more complex text
|
/// A wrapper around `NSMutableAttributedString`, which can be used for more complex text
|
||||||
/// rendering.
|
/// rendering.
|
||||||
///
|
///
|
||||||
pub struct AttributedString(pub Id<Object>);
|
pub struct AttributedString(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl AttributedString {
|
impl AttributedString {
|
||||||
/// Creates a blank AttributedString. Internally, this allocates an
|
/// Creates a blank AttributedString. Internally, this allocates an
|
||||||
|
@ -31,8 +30,8 @@ impl AttributedString {
|
||||||
let text = NSString::no_copy(value);
|
let text = NSString::no_copy(value);
|
||||||
|
|
||||||
Self(unsafe {
|
Self(unsafe {
|
||||||
let alloc: id = msg_send![class!(NSMutableAttributedString), alloc];
|
let alloc = msg_send_id![class!(NSMutableAttributedString), alloc];
|
||||||
Id::from_ptr(msg_send![alloc, initWithString:&*text])
|
msg_send_id![alloc, initWithString:&*text]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ impl AttributedString {
|
||||||
/// internal use, but kept available as part of the public API for the more adventurous types
|
/// internal use, but kept available as part of the public API for the more adventurous types
|
||||||
/// who might need it.
|
/// who might need it.
|
||||||
pub fn wrap(value: id) -> Self {
|
pub fn wrap(value: id) -> Self {
|
||||||
Self(unsafe { Id::from_ptr(msg_send![value, mutableCopy]) })
|
Self(unsafe { msg_send_id![value, mutableCopy] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the text (foreground) color for the specified range.
|
/// Sets the text (foreground) color for the specified range.
|
||||||
|
@ -49,19 +48,25 @@ impl AttributedString {
|
||||||
let range = CFRange::init(range.start, range.end);
|
let range = CFRange::init(range.start, range.end);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, addAttribute:NSForegroundColorAttributeName
|
let _: () = msg_send![
|
||||||
value:color
|
&*self.0,
|
||||||
range:range
|
addAttribute: NSForegroundColorAttributeName,
|
||||||
|
value: color,
|
||||||
|
range: range,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the font for the specified range.
|
/// Set the font for the specified range.
|
||||||
pub fn set_font(&mut self, font: Font, range: Range<isize>) {
|
pub fn set_font(&mut self, font: Font, range: Range<isize>) {
|
||||||
|
let range = CFRange::init(range.start, range.end);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, addAttribute:NSFontAttributeName
|
let _: () = msg_send![
|
||||||
value:&*font
|
&*self.0,
|
||||||
range:range
|
addAttribute: NSFontAttributeName,
|
||||||
|
value: &*font,
|
||||||
|
range: range,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +74,7 @@ impl AttributedString {
|
||||||
|
|
||||||
impl fmt::Display for AttributedString {
|
impl fmt::Display for AttributedString {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let string = NSString::from_retained(unsafe { msg_send![&*self.0, string] });
|
let string = NSString::from_id(unsafe { msg_send_id![&*self.0, string] });
|
||||||
|
|
||||||
write!(f, "{}", string.to_str())
|
write!(f, "{}", string.to_str())
|
||||||
}
|
}
|
||||||
|
@ -77,19 +82,12 @@ impl fmt::Display for AttributedString {
|
||||||
|
|
||||||
impl fmt::Debug for AttributedString {
|
impl fmt::Debug for AttributedString {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let string = NSString::from_retained(unsafe { msg_send![&*self.0, string] });
|
let string = NSString::from_id(unsafe { msg_send_id![&*self.0, string] });
|
||||||
|
|
||||||
f.debug_struct("AttributedString").field("text", &string.to_str()).finish()
|
f.debug_struct("AttributedString").field("text", &string.to_str()).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AttributedString> for id {
|
|
||||||
/// Consumes and returns the pointer to the underlying NSMutableAttributedString instance.
|
|
||||||
fn from(mut string: AttributedString) -> Self {
|
|
||||||
&mut *string.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for AttributedString {
|
impl Deref for AttributedString {
|
||||||
type Target = Object;
|
type Target = Object;
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ use std::ops::Deref;
|
||||||
|
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
|
||||||
use crate::utils::os;
|
use crate::utils::os;
|
||||||
|
@ -14,7 +14,7 @@ use crate::utils::os;
|
||||||
/// A `Font` can be constructed and applied to supported controls to control things like text
|
/// A `Font` can be constructed and applied to supported controls to control things like text
|
||||||
/// appearance and size.
|
/// appearance and size.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Font(pub ShareId<Object>);
|
pub struct Font(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl Default for Font {
|
impl Default for Font {
|
||||||
/// Returns the default `labelFont` on macOS.
|
/// Returns the default `labelFont` on macOS.
|
||||||
|
@ -23,10 +23,10 @@ impl Default for Font {
|
||||||
let default_size: id = unsafe { msg_send![cls, labelFontSize] };
|
let default_size: id = unsafe { msg_send![cls, labelFontSize] };
|
||||||
|
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
let font = Font(unsafe { ShareId::from_ptr(msg_send![cls, labelFontOfSize: default_size]) });
|
let font = Font(unsafe { msg_send_id![cls, labelFontOfSize: default_size] });
|
||||||
|
|
||||||
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
#[cfg(all(feature = "uikit", not(feature = "appkit")))]
|
||||||
let font = Font(unsafe { ShareId::from_ptr(msg_send![cls, systemFontOfSize: default_size]) });
|
let font = Font(unsafe { msg_send_id![cls, systemFontOfSize: default_size] });
|
||||||
font
|
font
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,14 @@ impl Font {
|
||||||
pub fn system(size: f64) -> Self {
|
pub fn system(size: f64) -> Self {
|
||||||
let size = size as CGFloat;
|
let size = size as CGFloat;
|
||||||
|
|
||||||
Font(unsafe { ShareId::from_ptr(msg_send![Self::class(), systemFontOfSize: size]) })
|
Font(unsafe { msg_send_id![Self::class(), systemFontOfSize: size] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and returns a default bold system font at the specified size.
|
/// Creates and returns a default bold system font at the specified size.
|
||||||
pub fn bold_system(size: f64) -> Self {
|
pub fn bold_system(size: f64) -> Self {
|
||||||
let size = size as CGFloat;
|
let size = size as CGFloat;
|
||||||
|
|
||||||
Font(unsafe { ShareId::from_ptr(msg_send![Self::class(), boldSystemFontOfSize: size]) })
|
Font(unsafe { msg_send_id![Self::class(), boldSystemFontOfSize: size] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and returns a monospace system font at the specified size and weight
|
/// Creates and returns a monospace system font at the specified size and weight
|
||||||
|
@ -67,9 +67,9 @@ impl Font {
|
||||||
let weight = weight as CGFloat;
|
let weight = weight as CGFloat;
|
||||||
|
|
||||||
if os::is_minimum_semversion(10, 15, 0) {
|
if os::is_minimum_semversion(10, 15, 0) {
|
||||||
Font(unsafe { ShareId::from_ptr(msg_send![class!(NSFont), monospacedSystemFontOfSize: size weight: weight]) })
|
Font(unsafe { msg_send_id![class!(NSFont), monospacedSystemFontOfSize: size, weight: weight] })
|
||||||
} else {
|
} else {
|
||||||
Font(unsafe { ShareId::from_ptr(msg_send![class!(NSFont), systemFontOfSize: size weight: weight ]) })
|
Font(unsafe { msg_send_id![class!(NSFont), systemFontOfSize: size, weight: weight] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR};
|
||||||
/// Injects an `NSTextField` subclass. This is used for the default views that don't use delegates - we
|
/// Injects an `NSTextField` 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
load_or_register_class("NSTextField", "RSTTextField", |decl| unsafe {})
|
load_or_register_class("NSTextField", "RSTTextField", |decl| unsafe {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> &'static Class {
|
||||||
load_or_register_class("NSView", "RSTTextFieldWithDelegate", |decl| unsafe {
|
load_or_register_class("NSView", "RSTTextFieldWithDelegate", |decl| unsafe {
|
||||||
// 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.
|
||||||
|
|
|
@ -43,9 +43,11 @@
|
||||||
//!
|
//!
|
||||||
//! For more information on Autolayout, view the module or check out the examples folder.
|
//! For more information on Autolayout, view the module or check out the examples folder.
|
||||||
|
|
||||||
|
use core_foundation::base::TCFType;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES};
|
||||||
|
@ -76,7 +78,7 @@ pub use traits::LabelDelegate;
|
||||||
pub(crate) static LABEL_DELEGATE_PTR: &str = "rstLabelDelegatePtr";
|
pub(crate) static LABEL_DELEGATE_PTR: &str = "rstLabelDelegatePtr";
|
||||||
|
|
||||||
/// A helper method for instantiating view classes and applying default settings to them.
|
/// A helper method for instantiating view classes and applying default settings to them.
|
||||||
fn allocate_view(registration_fn: fn() -> *const Class) -> id {
|
fn allocate_view(registration_fn: fn() -> &'static Class) -> id {
|
||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(feature = "appkit")]
|
#[cfg(feature = "appkit")]
|
||||||
let view: id = {
|
let view: id = {
|
||||||
|
@ -249,7 +251,7 @@ impl Label {
|
||||||
#[cfg(feature = "autolayout")]
|
#[cfg(feature = "autolayout")]
|
||||||
center_y: LayoutAnchorY::center(view),
|
center_y: LayoutAnchorY::center(view),
|
||||||
|
|
||||||
layer: Layer::wrap(unsafe { msg_send![view, layer] }),
|
layer: Layer::from_id(unsafe { msg_send_id![view, layer] }),
|
||||||
|
|
||||||
objc: ObjcProperty::retain(view)
|
objc: ObjcProperty::retain(view)
|
||||||
}
|
}
|
||||||
|
@ -324,7 +326,7 @@ impl<T> Label<T> {
|
||||||
// @TODO: This is wrong.
|
// @TODO: This is wrong.
|
||||||
// Needs to set ivar and such, akin to View.
|
// Needs to set ivar and such, akin to View.
|
||||||
self.objc.with_mut(|obj| unsafe {
|
self.objc.with_mut(|obj| unsafe {
|
||||||
let color = color.as_ref().cg_color();
|
let color = color.as_ref().cg_color().as_concrete_TypeRef();
|
||||||
let layer: id = msg_send![obj, layer];
|
let layer: id = msg_send![obj, layer];
|
||||||
let _: () = msg_send![layer, setBackgroundColor: color];
|
let _: () = msg_send![layer, setBackgroundColor: color];
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,8 +2,7 @@ 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, sel, sel_impl};
|
use objc::{class, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSUInteger, NO, YES};
|
use crate::foundation::{id, NSUInteger, NO, YES};
|
||||||
use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR};
|
use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR};
|
||||||
|
@ -11,23 +10,23 @@ use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR};
|
||||||
/// Injects an `UILabel` subclass. This is used for the default views that don't use delegates - we
|
/// Injects an `UILabel` 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<&'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
let superclass = class!(UILabel);
|
let superclass = class!(UILabel);
|
||||||
let decl = ClassDecl::new("RSTTextField", superclass).unwrap();
|
let decl = ClassDecl::new("RSTTextField", superclass).unwrap();
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Injects an `UILabel` subclass, with some callback and pointer ivars for what we
|
/// Injects an `UILabel` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> &'static Class {
|
||||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
static mut VIEW_CLASS: Option<&'static Class> = None;
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
INIT.call_once(|| unsafe {
|
INIT.call_once(|| unsafe {
|
||||||
|
@ -38,8 +37,8 @@ pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Cl
|
||||||
// move.
|
// move.
|
||||||
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
|
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
|
||||||
|
|
||||||
VIEW_CLASS = decl.register();
|
VIEW_CLASS = Some(decl.register());
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { VIEW_CLASS }
|
unsafe { VIEW_CLASS.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use objc::runtime::Class;
|
||||||
use crate::foundation::load_or_register_class_with_optional_generated_suffix;
|
use crate::foundation::load_or_register_class_with_optional_generated_suffix;
|
||||||
|
|
||||||
/// Used for injecting a custom UIApplication. Currently does nothing.
|
/// Used for injecting a custom UIApplication. Currently does nothing.
|
||||||
pub(crate) fn register_app_class() -> *const Class {
|
pub(crate) fn register_app_class() -> &'static Class {
|
||||||
let should_generate_suffix = false;
|
let should_generate_suffix = false;
|
||||||
|
|
||||||
load_or_register_class_with_optional_generated_suffix("UIApplication", "RSTApplication", should_generate_suffix, |decl| {})
|
load_or_register_class_with_optional_generated_suffix("UIApplication", "RSTApplication", should_generate_suffix, |decl| {})
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
//! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook
|
//! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook
|
||||||
//! for potential future use.
|
//! for potential future use.
|
||||||
|
|
||||||
use objc::runtime::{Class, Object, Sel};
|
use objc::rc::Id;
|
||||||
use objc::{sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
|
use objc::sel;
|
||||||
|
|
||||||
//use crate::error::Error;
|
//use crate::error::Error;
|
||||||
use crate::foundation::{id, load_or_register_class_with_optional_generated_suffix, BOOL, YES};
|
use crate::foundation::{id, load_or_register_class_with_optional_generated_suffix};
|
||||||
use crate::uikit::app::{AppDelegate, APP_DELEGATE};
|
use crate::uikit::app::{AppDelegate, APP_DELEGATE};
|
||||||
use crate::uikit::scene::{SceneConnectionOptions, SceneSession};
|
use crate::uikit::scene::{SceneConnectionOptions, SceneSession};
|
||||||
|
|
||||||
|
@ -27,37 +28,39 @@ fn app<T>(this: &Object) -> &T {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fires when the Application Delegate receives a `applicationDidFinishLaunching` notification.
|
/// Fires when the Application Delegate receives a `applicationDidFinishLaunching` notification.
|
||||||
extern "C" fn did_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id, _: id) -> BOOL {
|
extern "C" fn did_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id, _: id) -> Bool {
|
||||||
app::<T>(this).did_finish_launching();
|
app::<T>(this).did_finish_launching();
|
||||||
YES
|
Bool::YES
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn configuration_for_scene_session<T: AppDelegate>(this: &Object, _: Sel, _: id, session: id, opts: id) -> id {
|
extern "C" fn configuration_for_scene_session<T: AppDelegate>(this: &Object, _: Sel, _: id, session: id, opts: id) -> id {
|
||||||
app::<T>(this)
|
Id::autorelease_return(
|
||||||
.config_for_scene_session(SceneSession::with(session), SceneConnectionOptions::with(opts))
|
app::<T>(this)
|
||||||
.into_inner()
|
.config_for_scene_session(SceneSession::with(session), SceneConnectionOptions::with(opts))
|
||||||
|
.0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
||||||
/// pointers we need to have.
|
/// pointers we need to have.
|
||||||
pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class {
|
pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> &'static Class {
|
||||||
let should_generate_suffix = false;
|
let should_generate_suffix = false;
|
||||||
|
|
||||||
load_or_register_class_with_optional_generated_suffix("NSObject", "RSTAppDelegate", should_generate_suffix, |decl| unsafe {
|
load_or_register_class_with_optional_generated_suffix("NSObject", "RSTAppDelegate", should_generate_suffix, |decl| unsafe {
|
||||||
// Launching Applications
|
// Launching Applications
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:didFinishLaunchingWithOptions:),
|
sel!(application:didFinishLaunchingWithOptions:),
|
||||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
did_finish_launching::<T> as extern "C" fn(_, _, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
// Scenes
|
// Scenes
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(application:configurationForConnectingSceneSession:options:),
|
sel!(application:configurationForConnectingSceneSession:options:),
|
||||||
configuration_for_scene_session::<T> as extern "C" fn(&Object, _, _, id, id) -> id
|
configuration_for_scene_session::<T> as extern "C" fn(_, _, _, _, _) -> _
|
||||||
);
|
);
|
||||||
/*decl.add_method(
|
/*decl.add_method(
|
||||||
sel!(application:didDiscardSceneSessions:),
|
sel!(application:didDiscardSceneSessions:),
|
||||||
did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id)
|
did_discard_scene_sessions::<T> as extern "C" fn(_, _, _, _)
|
||||||
);*/
|
);*/
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ use libc::{c_char, c_int};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, nil, AutoReleasePool, NSString, NSUInteger, NO, YES};
|
use crate::foundation::{id, nil, AutoReleasePool, NSString, NSUInteger, NO, YES};
|
||||||
use crate::notification_center::Dispatcher;
|
use crate::notification_center::Dispatcher;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class, ClassMap, NSString};
|
use crate::foundation::{id, load_or_register_class, ClassMap, NSString};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use crate::uikit::scene::SessionRole;
|
||||||
///
|
///
|
||||||
/// Due to the way we have to implement this, you likely never need to touch this.
|
/// Due to the way we have to implement this, you likely never need to touch this.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SceneConfig(Id<Object>);
|
pub struct SceneConfig(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl SceneConfig {
|
impl SceneConfig {
|
||||||
/// Creates a new `UISceneConfiguration` with the specified name and session role, retains it,
|
/// Creates a new `UISceneConfiguration` with the specified name and session role, retains it,
|
||||||
|
@ -24,20 +24,15 @@ impl SceneConfig {
|
||||||
let role = NSString::from(role);
|
let role = NSString::from(role);
|
||||||
|
|
||||||
let cls = class!(UISceneConfiguration);
|
let cls = class!(UISceneConfiguration);
|
||||||
let config: id = msg_send![cls, configurationWithName:name sessionRole:role];
|
let mut config = msg_send_id![cls, configurationWithName: &*name, sessionRole: &*role];
|
||||||
|
|
||||||
let _: () = msg_send![config, setSceneClass: class!(UIWindowScene)];
|
let _: () = msg_send![&mut config, setSceneClass: class!(UIWindowScene)];
|
||||||
|
|
||||||
// TODO: use register_window_scene_delegate_class rather than load_or_register_class.
|
// TODO: use register_window_scene_delegate_class rather than load_or_register_class.
|
||||||
let window_delegate = load_or_register_class("UIResponder", "RSTWindowSceneDelegate", |decl| unsafe {});
|
let window_delegate = load_or_register_class("UIResponder", "RSTWindowSceneDelegate", |decl| unsafe {});
|
||||||
let _: () = msg_send![config, setDelegateClass: window_delegate];
|
let _: () = msg_send![&mut config, setDelegateClass: window_delegate];
|
||||||
|
|
||||||
Id::from_ptr(config)
|
config
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes and returns the underlying `UISceneConfiguration`.
|
|
||||||
pub fn into_inner(mut self) -> id {
|
|
||||||
&mut *self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use objc::runtime::{Class, Object, Protocol, Sel};
|
use objc::runtime::{Class, Object, Protocol, Sel};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::foundation::{id, load_or_register_class_with_optional_generated_suffix};
|
use crate::foundation::{id, load_or_register_class_with_optional_generated_suffix};
|
||||||
use crate::uikit::app::SCENE_DELEGATE_VENDOR;
|
use crate::uikit::app::SCENE_DELEGATE_VENDOR;
|
||||||
|
@ -9,9 +9,9 @@ use crate::utils::load;
|
||||||
pub(crate) static WINDOW_SCENE_PTR: &str = "rstWindowSceneDelegatePtr";
|
pub(crate) static WINDOW_SCENE_PTR: &str = "rstWindowSceneDelegatePtr";
|
||||||
|
|
||||||
///
|
///
|
||||||
extern "C" fn init<T: WindowSceneDelegate, F: Fn() -> Box<T>>(this: &mut Object, _: Sel) -> id {
|
extern "C" fn init<T: WindowSceneDelegate, F: Fn() -> Box<T>>(mut this: &mut Object, _: Sel) -> id {
|
||||||
let x = unsafe {
|
let x = unsafe {
|
||||||
*this = msg_send![super(this, class!(UIResponder)), init];
|
this = msg_send![super(this, class!(UIResponder)), init];
|
||||||
|
|
||||||
let scene_delegate_vendor = SCENE_DELEGATE_VENDOR as *const F;
|
let scene_delegate_vendor = SCENE_DELEGATE_VENDOR as *const F;
|
||||||
let factory: &F = &*scene_delegate_vendor;
|
let factory: &F = &*scene_delegate_vendor;
|
||||||
|
@ -44,7 +44,7 @@ extern "C" fn scene_will_connect_to_session_with_options<T: WindowSceneDelegate>
|
||||||
|
|
||||||
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and
|
||||||
/// pointers we need to have.
|
/// pointers we need to have.
|
||||||
pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class {
|
pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> &'static Class {
|
||||||
let should_generate_suffix = false;
|
let should_generate_suffix = false;
|
||||||
|
|
||||||
load_or_register_class_with_optional_generated_suffix("UIResponder", "RSTWindowSceneDelegate", false, |decl| unsafe {
|
load_or_register_class_with_optional_generated_suffix("UIResponder", "RSTWindowSceneDelegate", false, |decl| unsafe {
|
||||||
|
@ -55,12 +55,12 @@ pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn
|
||||||
decl.add_protocol(p);
|
decl.add_protocol(p);
|
||||||
|
|
||||||
// Override the `init` call to handle creating and attaching a WindowSceneDelegate.
|
// Override the `init` call to handle creating and attaching a WindowSceneDelegate.
|
||||||
decl.add_method(sel!(init), init::<T, F> as extern "C" fn(&mut Object, _) -> id);
|
decl.add_method(sel!(init), init::<T, F> as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
// UIWindowSceneDelegate API
|
// UIWindowSceneDelegate API
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(scene:willConnectToSession:options:),
|
sel!(scene:willConnectToSession:options:),
|
||||||
scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _)
|
scene_will_connect_to_session_with_options::<T> as extern "C" fn(_, _, _, _, _)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
use core_graphics::geometry::CGRect;
|
use core_graphics::geometry::CGRect;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
|
@ -31,11 +31,11 @@ mod session;
|
||||||
pub use session::*;
|
pub use session::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Scene(pub Id<Object>);
|
pub struct Scene(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
pub fn with(scene: id) -> Self {
|
pub fn with(scene: id) -> Self {
|
||||||
Scene(unsafe { Id::from_ptr(scene) })
|
Scene(unsafe { Id::retain(scene).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is temporary - I'm not wrapping `coordinateSpace` until I'm happy with the ergonomics
|
// This is temporary - I'm not wrapping `coordinateSpace` until I'm happy with the ergonomics
|
||||||
|
@ -48,8 +48,4 @@ impl Scene {
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_inner(mut self) -> id {
|
|
||||||
&mut *self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
|
|
||||||
|
@ -8,15 +8,10 @@ use crate::foundation::{id, NSString};
|
||||||
///
|
///
|
||||||
/// Due to the way we have to implement this, you likely never need to touch this.
|
/// Due to the way we have to implement this, you likely never need to touch this.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SceneConnectionOptions(Id<Object>);
|
pub struct SceneConnectionOptions(Id<Object, Owned>);
|
||||||
|
|
||||||
impl SceneConnectionOptions {
|
impl SceneConnectionOptions {
|
||||||
pub fn with(opts: id) -> Self {
|
pub fn with(opts: id) -> Self {
|
||||||
SceneConnectionOptions(unsafe { Id::from_ptr(opts) })
|
SceneConnectionOptions(unsafe { Id::retain(opts).unwrap() })
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes and returns the underlying `UISceneConfiguration`.
|
|
||||||
pub fn into_inner(mut self) -> id {
|
|
||||||
&mut *self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
use crate::uikit::scene::enums::SessionRole;
|
use crate::uikit::scene::enums::SessionRole;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SceneSession(pub Id<Object>);
|
pub struct SceneSession(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl SceneSession {
|
impl SceneSession {
|
||||||
pub fn with(session: id) -> Self {
|
pub fn with(session: id) -> Self {
|
||||||
SceneSession(unsafe { Id::from_ptr(session) })
|
SceneSession(unsafe { Id::retain(session).unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn role(&self) -> SessionRole {
|
pub fn role(&self) -> SessionRole {
|
||||||
NSString::from_retained(unsafe { msg_send![&*self.0, role] }).into()
|
NSString::from_id(unsafe { msg_send_id![&*self.0, role] }).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use core_graphics::geometry::CGRect;
|
use core_graphics::geometry::CGRect;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
use crate::geometry::Rect;
|
use crate::geometry::Rect;
|
||||||
|
@ -10,20 +10,20 @@ use crate::uikit::Scene;
|
||||||
use crate::utils::Controller;
|
use crate::utils::Controller;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Window(pub Id<Object>);
|
pub struct Window(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(frame: Rect) -> Self {
|
pub fn new(frame: Rect) -> Self {
|
||||||
Window(unsafe {
|
Window(unsafe {
|
||||||
let rect: CGRect = frame.into();
|
let rect: CGRect = frame.into();
|
||||||
let alloc: id = msg_send![class!(UIWindow), alloc];
|
let alloc = msg_send_id![class!(UIWindow), alloc];
|
||||||
Id::from_ptr(msg_send![alloc, initWithFrame: rect])
|
msg_send_id![alloc, initWithFrame: rect]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_window_scene(&mut self, scene: Scene) {
|
pub fn set_window_scene(&mut self, scene: Scene) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, setWindowScene:scene.into_inner()];
|
let _: () = msg_send![&*self.0, setWindowScene: &*scene.0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
//!
|
//!
|
||||||
//! This is primarily used in handling app handoff between devices.
|
//! This is primarily used in handling app handoff between devices.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
/// Represents an `NSUserActivity`, which acts as a lightweight method to capture
|
/// Represents an `NSUserActivity`, which acts as a lightweight method to capture
|
||||||
/// the state of your app.
|
/// the state of your app.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UserActivity(pub ShareId<Object>);
|
pub struct UserActivity(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl UserActivity {
|
impl UserActivity {
|
||||||
/// An internal method for wrapping a system-provided activity.
|
/// An internal method for wrapping a system-provided activity.
|
||||||
pub(crate) fn with_inner(object: id) -> Self {
|
pub(crate) fn with_inner(object: id) -> Self {
|
||||||
UserActivity(unsafe { ShareId::from_ptr(object) })
|
UserActivity(unsafe { Id::retain(object).unwrap() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::foundation::{id, nil, NSString, NSUInteger};
|
use crate::foundation::{id, nil, NSString, NSUInteger};
|
||||||
|
@ -27,7 +27,7 @@ impl NotificationCenter {
|
||||||
unsafe {
|
unsafe {
|
||||||
// @TODO: Revisit.
|
// @TODO: Revisit.
|
||||||
let block = ConcreteBlock::new(|_: id, error: id| {
|
let block = ConcreteBlock::new(|_: id, error: id| {
|
||||||
let localized_description = NSString::new(msg_send![error, localizedDescription]);
|
let localized_description = NSString::retain(msg_send![error, localizedDescription]);
|
||||||
let e = localized_description.to_str();
|
let e = localized_description.to_str();
|
||||||
if e != "" {
|
if e != "" {
|
||||||
println!("{:?}", e);
|
println!("{:?}", e);
|
||||||
|
@ -41,7 +41,11 @@ impl NotificationCenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let center: id = msg_send![class!(UNUserNotificationCenter), currentNotificationCenter];
|
let center: id = msg_send![class!(UNUserNotificationCenter), currentNotificationCenter];
|
||||||
let _: () = msg_send![center, requestAuthorizationWithOptions:opts completionHandler:block.copy()];
|
let _: () = msg_send![
|
||||||
|
center,
|
||||||
|
requestAuthorizationWithOptions:opts,
|
||||||
|
completionHandler: &*block.copy(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +55,12 @@ impl NotificationCenter {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let identifier = NSString::new(&uuidentifier);
|
let identifier = NSString::new(&uuidentifier);
|
||||||
let request: id =
|
let request: id = msg_send![
|
||||||
msg_send![class!(UNNotificationRequest), requestWithIdentifier:identifier content:&*notification.0 trigger:nil];
|
class!(UNNotificationRequest),
|
||||||
|
requestWithIdentifier: &*identifier,
|
||||||
|
content: &*notification.0,
|
||||||
|
trigger: nil,
|
||||||
|
];
|
||||||
let center: id = msg_send![class!(UNUserNotificationCenter), currentNotificationCenter];
|
let center: id = msg_send![class!(UNUserNotificationCenter), currentNotificationCenter];
|
||||||
let _: () = msg_send![center, addNotificationRequest: request];
|
let _: () = msg_send![center, addNotificationRequest: request];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
//! Acts as a (currently dumb) wrapper for `UNMutableNotificationContent`, which is what you mostly
|
//! Acts as a (currently dumb) wrapper for `UNMutableNotificationContent`, which is what you mostly
|
||||||
//! need to pass to the notification center for things to work.
|
//! need to pass to the notification center for things to work.
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, msg_send_id, sel};
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::{id, NSString};
|
use crate::foundation::{id, NSString};
|
||||||
|
|
||||||
/// A wrapper for `UNMutableNotificationContent`. Retains the pointer from the Objective C side,
|
/// A wrapper for `UNMutableNotificationContent`. Retains the pointer from the Objective C side,
|
||||||
/// and is ultimately dropped upon sending.
|
/// and is ultimately dropped upon sending.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Notification(pub Id<Object>);
|
pub struct Notification(pub Id<Object, Owned>);
|
||||||
|
|
||||||
impl Notification {
|
impl Notification {
|
||||||
/// Constructs a new `Notification`. This allocates `NSString`'s, as it has to do so for the
|
/// Constructs a new `Notification`. This allocates `NSString`'s, as it has to do so for the
|
||||||
|
@ -20,10 +20,10 @@ impl Notification {
|
||||||
let body = NSString::new(body);
|
let body = NSString::new(body);
|
||||||
|
|
||||||
Notification(unsafe {
|
Notification(unsafe {
|
||||||
let content: id = msg_send![class!(UNMutableNotificationContent), new];
|
let mut content = msg_send_id![class!(UNMutableNotificationContent), new];
|
||||||
let _: () = msg_send![content, setTitle: title];
|
let _: () = msg_send![&mut content, setTitle: &*title];
|
||||||
let _: () = msg_send![content, setBody: body];
|
let _: () = msg_send![&mut content, setBody: &*body];
|
||||||
Id::from_ptr(content)
|
content
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
//! belong to. These are typically internal, and if you rely on them... well, don't be surprised if
|
//! belong to. These are typically internal, and if you rely on them... well, don't be surprised if
|
||||||
//! they go away one day.
|
//! they go away one day.
|
||||||
|
|
||||||
|
use core_foundation::base::CFIndex;
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc::{Encode, Encoding};
|
use objc::{Encode, Encoding};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::{id, BOOL, NO, YES};
|
use crate::foundation::{id, BOOL, NO, YES};
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ pub mod properties;
|
||||||
/// a guard for whether something is a (View|Window|etc)Controller.
|
/// a guard for whether something is a (View|Window|etc)Controller.
|
||||||
pub trait Controller {
|
pub trait Controller {
|
||||||
/// Returns the underlying Objective-C object.
|
/// Returns the underlying Objective-C object.
|
||||||
fn get_backing_node(&self) -> ShareId<Object>;
|
fn get_backing_node(&self) -> Id<Object, Shared>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility method for taking a pointer and grabbing the corresponding delegate in Rust. This is
|
/// Utility method for taking a pointer and grabbing the corresponding delegate in Rust. This is
|
||||||
|
@ -92,14 +93,29 @@ impl CGSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Encode for CGSize {
|
unsafe impl Encode for CGSize {
|
||||||
/// Adds support for CGSize Objective-C encoding.
|
const ENCODING: Encoding = Encoding::Struct("CGSize", &[CGFloat::ENCODING, CGFloat::ENCODING]);
|
||||||
fn encode() -> Encoding {
|
}
|
||||||
let encoding = format!("{{CGSize={}{}}}", CGFloat::encode().as_str(), CGFloat::encode().as_str());
|
|
||||||
|
|
||||||
unsafe { Encoding::from_str(&encoding) }
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||||
|
pub struct CFRange {
|
||||||
|
pub location: CFIndex,
|
||||||
|
pub length: CFIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CFRange {
|
||||||
|
pub fn init(location: CFIndex, length: CFIndex) -> CFRange {
|
||||||
|
CFRange {
|
||||||
|
location: location,
|
||||||
|
length: length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Encode for CFRange {
|
||||||
|
const ENCODING: Encoding = Encoding::Struct("CFRange", &[CFIndex::ENCODING, CFIndex::ENCODING]);
|
||||||
|
}
|
||||||
|
|
||||||
/// A helper method for ensuring that Cocoa is running in multi-threaded mode.
|
/// A helper method for ensuring that Cocoa is running in multi-threaded mode.
|
||||||
///
|
///
|
||||||
/// Why do we need this? According to Apple, if you're going to make use of standard POSIX threads,
|
/// Why do we need this? According to Apple, if you're going to make use of standard POSIX threads,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Owned};
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
use objc_id::Id;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
|
@ -15,17 +15,12 @@ use crate::foundation::id;
|
||||||
/// It is possible we could remove the `Id` wrapper in here if we're just doing this ourselves, and
|
/// It is possible we could remove the `Id` wrapper in here if we're just doing this ourselves, and
|
||||||
/// is probably worth investigating at some point.
|
/// is probably worth investigating at some point.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ObjcProperty(Rc<RefCell<Id<Object>>>);
|
pub struct ObjcProperty(Rc<RefCell<Id<Object, Owned>>>);
|
||||||
|
|
||||||
impl ObjcProperty {
|
impl ObjcProperty {
|
||||||
/// Given an Objective-C object, retains it and wraps it as a `Property`.
|
/// Given an Objective-C object, retains it and wraps it as a `Property`.
|
||||||
pub fn retain(obj: id) -> Self {
|
pub fn retain(obj: id) -> Self {
|
||||||
ObjcProperty(Rc::new(RefCell::new(unsafe { Id::from_ptr(obj) })))
|
ObjcProperty(Rc::new(RefCell::new(unsafe { Id::retain(obj).unwrap() })))
|
||||||
}
|
|
||||||
|
|
||||||
/// Given an Objective-C object, retains it and wraps it as a `Property`.
|
|
||||||
pub fn from_retained(obj: id) -> Self {
|
|
||||||
ObjcProperty(Rc::new(RefCell::new(unsafe { Id::from_retained_ptr(obj) })))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a handler with mutable access for the underlying Objective-C object.
|
/// Runs a handler with mutable access for the underlying Objective-C object.
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
use core_graphics::base::CGFloat;
|
use core_graphics::base::CGFloat;
|
||||||
|
|
||||||
|
use objc::rc::{Id, Shared};
|
||||||
use objc::runtime::{Class, Object};
|
use objc::runtime::{Class, Object};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, msg_send_id, sel};
|
||||||
use objc_id::ShareId;
|
|
||||||
|
|
||||||
use crate::foundation::id;
|
use crate::foundation::id;
|
||||||
|
|
||||||
/// A wrapper for an animation proxy object in Cocoa that supports basic animations.
|
/// A wrapper for an animation proxy object in Cocoa that supports basic animations.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ViewAnimatorProxy(pub ShareId<Object>);
|
pub struct ViewAnimatorProxy(pub Id<Object, Shared>);
|
||||||
|
|
||||||
impl ViewAnimatorProxy {
|
impl ViewAnimatorProxy {
|
||||||
pub fn new(proxy: id) -> Self {
|
pub fn new(proxy: id) -> Self {
|
||||||
Self(unsafe { ShareId::from_ptr(msg_send![proxy, animator]) })
|
Self(unsafe { msg_send_id![proxy, animator] })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the alpha value for the view being animated.
|
/// Sets the alpha value for the view being animated.
|
||||||
|
@ -22,3 +22,7 @@ impl ViewAnimatorProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Safety
|
||||||
|
unsafe impl Send for ViewAnimatorProxy {}
|
||||||
|
unsafe impl Sync for ViewAnimatorProxy {}
|
||||||
|
|
|
@ -8,51 +8,45 @@
|
||||||
//! color, and enforcing layer backing by default.
|
//! color, and enforcing layer backing by default.
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL};
|
use objc::rc::{Id, Owned};
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::runtime::{Bool, Class, Object, Sel};
|
||||||
use objc_id::Id;
|
use objc::{class, msg_send, sel};
|
||||||
|
|
||||||
use crate::dragdrop::DragInfo;
|
use crate::dragdrop::DragInfo;
|
||||||
use crate::foundation::{id, load_or_register_class, nil, NSUInteger, NO, YES};
|
use crate::foundation::{id, load_or_register_class, nil, NSUInteger};
|
||||||
use crate::utils::load;
|
use crate::utils::load;
|
||||||
use crate::view::{ViewDelegate, BACKGROUND_COLOR, VIEW_DELEGATE_PTR};
|
use crate::view::{ViewDelegate, BACKGROUND_COLOR, VIEW_DELEGATE_PTR};
|
||||||
|
|
||||||
/// 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.
|
||||||
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> Bool {
|
||||||
return YES;
|
return Bool::YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn dragging_entered<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
|
extern "C" 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);
|
||||||
view.dragging_entered(DragInfo {
|
view.dragging_entered(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn prepare_for_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.prepare_for_drag_operation(DragInfo {
|
Bool::new(view.prepare_for_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
extern "C" fn perform_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> BOOL {
|
extern "C" fn perform_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel, info: id) -> Bool {
|
||||||
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
match view.perform_drag_operation(DragInfo {
|
Bool::new(view.perform_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
}) {
|
}))
|
||||||
true => YES,
|
|
||||||
false => NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when a drag/drop operation has entered this view.
|
/// Called when a drag/drop operation has entered this view.
|
||||||
|
@ -60,7 +54,7 @@ extern "C" fn conclude_drag_operation<T: ViewDelegate>(this: &mut Object, _: Sel
|
||||||
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.conclude_drag_operation(DragInfo {
|
view.conclude_drag_operation(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +63,7 @@ extern "C" fn dragging_exited<T: ViewDelegate>(this: &mut Object, _: Sel, info:
|
||||||
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
let view = load::<T>(this, VIEW_DELEGATE_PTR);
|
||||||
|
|
||||||
view.dragging_exited(DragInfo {
|
view.dragging_exited(DragInfo {
|
||||||
info: unsafe { Id::from_ptr(info) }
|
info: unsafe { Id::retain(info).unwrap() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +83,11 @@ extern "C" fn update_layer(this: &Object, _: Sel) {
|
||||||
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
|
/// 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
|
/// have separate classes here since we don't want to waste cycles on methods that will never be
|
||||||
/// used if there's no delegates.
|
/// used if there's no delegates.
|
||||||
pub(crate) fn register_view_class() -> *const Class {
|
pub(crate) fn register_view_class() -> &'static Class {
|
||||||
load_or_register_class("NSView", "RSTView", |decl| unsafe {
|
load_or_register_class("NSView", "RSTView", |decl| unsafe {
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(_, _));
|
||||||
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||||
})
|
})
|
||||||
|
@ -101,43 +95,37 @@ pub(crate) fn register_view_class() -> *const Class {
|
||||||
|
|
||||||
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we
|
||||||
/// need to do.
|
/// need to do.
|
||||||
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>(instance: &T) -> *const Class {
|
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>(instance: &T) -> &'static Class {
|
||||||
load_or_register_class("NSView", instance.subclass_name(), |decl| unsafe {
|
load_or_register_class("NSView", instance.subclass_name(), |decl| unsafe {
|
||||||
// A pointer to the ViewDelegate instance on the Rust side.
|
// A pointer to the ViewDelegate instance on the Rust side.
|
||||||
// It's expected that this doesn't move.
|
// It's expected that this doesn't move.
|
||||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||||
|
|
||||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(_, _));
|
||||||
|
|
||||||
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(_, _) -> _);
|
||||||
|
|
||||||
// Drag and drop operations (e.g, accepting files)
|
// Drag and drop operations (e.g, accepting files)
|
||||||
decl.add_method(
|
decl.add_method(sel!(draggingEntered:), dragging_entered::<T> as extern "C" fn(_, _, _) -> _);
|
||||||
sel!(draggingEntered:),
|
|
||||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
|
||||||
);
|
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(prepareForDragOperation:),
|
sel!(prepareForDragOperation:),
|
||||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
prepare_for_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(performDragOperation:),
|
sel!(performDragOperation:),
|
||||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
perform_drag_operation::<T> as extern "C" fn(_, _, _) -> _
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(concludeDragOperation:),
|
sel!(concludeDragOperation:),
|
||||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
conclude_drag_operation::<T> as extern "C" fn(_, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
decl.add_method(
|
decl.add_method(sel!(draggingExited:), dragging_exited::<T> as extern "C" fn(_, _, _));
|
||||||
sel!(draggingExited:),
|
|
||||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue