Fixes possible duplicate objc class registration.
This can happen in environments like plugins, where cacao can exist multiple times and thus tries to create and register its objc classes more than once.
This commit is contained in:
parent
1d76dce75f
commit
2803922f3a
|
@ -12,12 +12,17 @@ use objc::runtime::Class;
|
|||
pub(crate) fn register_app_class() -> *const Class {
|
||||
static mut APP_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTApplication";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSApplication);
|
||||
let decl = ClassDecl::new("RSTApplication", superclass).unwrap();
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { APP_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSApplication);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { APP_CLASS }
|
||||
}
|
||||
|
|
|
@ -297,173 +297,178 @@ extern "C" fn delegate_handles_key<T: AppDelegate>(this: &Object, _: Sel, _: id,
|
|||
pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class {
|
||||
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTAppDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { DELEGATE_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
decl.add_ivar::<usize>(APP_PTR);
|
||||
decl.add_ivar::<usize>(APP_PTR);
|
||||
|
||||
// Launching Applications
|
||||
decl.add_method(
|
||||
sel!(applicationWillFinishLaunching:),
|
||||
will_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidFinishLaunching:),
|
||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
// Launching Applications
|
||||
decl.add_method(
|
||||
sel!(applicationWillFinishLaunching:),
|
||||
will_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidFinishLaunching:),
|
||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
|
||||
// Managing Active Status
|
||||
decl.add_method(
|
||||
sel!(applicationWillBecomeActive:),
|
||||
will_become_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidBecomeActive:),
|
||||
did_become_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillResignActive:),
|
||||
will_resign_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidResignActive:),
|
||||
did_resign_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
// Managing Active Status
|
||||
decl.add_method(
|
||||
sel!(applicationWillBecomeActive:),
|
||||
will_become_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidBecomeActive:),
|
||||
did_become_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillResignActive:),
|
||||
will_resign_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidResignActive:),
|
||||
did_resign_active::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
|
||||
// Terminating Applications
|
||||
decl.add_method(
|
||||
sel!(applicationShouldTerminate:),
|
||||
should_terminate::<T> as extern "C" fn(&Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillTerminate:),
|
||||
will_terminate::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationShouldTerminateAfterLastWindowClosed:),
|
||||
should_terminate_after_last_window_closed::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
// Terminating Applications
|
||||
decl.add_method(
|
||||
sel!(applicationShouldTerminate:),
|
||||
should_terminate::<T> as extern "C" fn(&Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationWillTerminate:),
|
||||
will_terminate::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationShouldTerminateAfterLastWindowClosed:),
|
||||
should_terminate_after_last_window_closed::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
|
||||
// Hiding Applications
|
||||
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _));
|
||||
// Hiding Applications
|
||||
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _));
|
||||
|
||||
// Managing Windows
|
||||
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(
|
||||
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
|
||||
should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL
|
||||
);
|
||||
// Managing Windows
|
||||
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
|
||||
decl.add_method(
|
||||
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
|
||||
should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL
|
||||
);
|
||||
|
||||
// Dock Menu
|
||||
decl.add_method(
|
||||
sel!(applicationDockMenu:),
|
||||
dock_menu::<T> as extern "C" fn(&Object, _, _) -> id
|
||||
);
|
||||
// Dock Menu
|
||||
decl.add_method(
|
||||
sel!(applicationDockMenu:),
|
||||
dock_menu::<T> as extern "C" fn(&Object, _, _) -> id
|
||||
);
|
||||
|
||||
// Displaying Errors
|
||||
decl.add_method(
|
||||
sel!(application:willPresentError:),
|
||||
will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id
|
||||
);
|
||||
// Displaying Errors
|
||||
decl.add_method(
|
||||
sel!(application:willPresentError:),
|
||||
will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id
|
||||
);
|
||||
|
||||
// Managing the Screen
|
||||
decl.add_method(
|
||||
sel!(applicationDidChangeScreenParameters:),
|
||||
did_change_screen_parameters::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidChangeOcclusionState:),
|
||||
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
// Managing the Screen
|
||||
decl.add_method(
|
||||
sel!(applicationDidChangeScreenParameters:),
|
||||
did_change_screen_parameters::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidChangeOcclusionState:),
|
||||
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
|
||||
);
|
||||
|
||||
// User Activities
|
||||
decl.add_method(
|
||||
sel!(application:willContinueUserActivityWithType:),
|
||||
will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:continueUserActivity:restorationHandler:),
|
||||
continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didFailToContinueUserActivityWithType:error:),
|
||||
failed_to_continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didUpdateUserActivity:),
|
||||
did_update_user_activity::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
// User Activities
|
||||
decl.add_method(
|
||||
sel!(application:willContinueUserActivityWithType:),
|
||||
will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:continueUserActivity:restorationHandler:),
|
||||
continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didFailToContinueUserActivityWithType:error:),
|
||||
failed_to_continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didUpdateUserActivity:),
|
||||
did_update_user_activity::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
|
||||
// Handling push notifications
|
||||
decl.add_method(
|
||||
sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
|
||||
registered_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didFailToRegisterForRemoteNotificationsWithError:),
|
||||
failed_to_register_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didReceiveRemoteNotification:),
|
||||
did_receive_remote_notification::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
// Handling push notifications
|
||||
decl.add_method(
|
||||
sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
|
||||
registered_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didFailToRegisterForRemoteNotificationsWithError:),
|
||||
failed_to_register_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:didReceiveRemoteNotification:),
|
||||
did_receive_remote_notification::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
|
||||
// CloudKit
|
||||
#[cfg(feature = "cloudkit")]
|
||||
decl.add_method(
|
||||
sel!(application:userDidAcceptCloudKitShareWithMetadata:),
|
||||
accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
// CloudKit
|
||||
#[cfg(feature = "cloudkit")]
|
||||
decl.add_method(
|
||||
sel!(application:userDidAcceptCloudKitShareWithMetadata:),
|
||||
accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
|
||||
// Opening Files
|
||||
decl.add_method(
|
||||
sel!(application:openURLs:),
|
||||
open_urls::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openFileWithoutUI:),
|
||||
open_file_without_ui::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationShouldOpenUntitledFile:),
|
||||
should_open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationOpenUntitledFile:),
|
||||
open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openTempFile:),
|
||||
open_temp_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
// Opening Files
|
||||
decl.add_method(
|
||||
sel!(application:openURLs:),
|
||||
open_urls::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openFileWithoutUI:),
|
||||
open_file_without_ui::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationShouldOpenUntitledFile:),
|
||||
should_open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationOpenUntitledFile:),
|
||||
open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openTempFile:),
|
||||
open_temp_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
|
||||
// Printing
|
||||
decl.add_method(
|
||||
sel!(application:printFile:),
|
||||
print_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:printFiles:withSettings:showPrintPanels:),
|
||||
print_files::<T> as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger
|
||||
);
|
||||
// Printing
|
||||
decl.add_method(
|
||||
sel!(application:printFile:),
|
||||
print_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:printFiles:withSettings:showPrintPanels:),
|
||||
print_files::<T> as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger
|
||||
);
|
||||
|
||||
// @TODO: Restoring Application State
|
||||
// Depends on NSCoder support, which is... welp.
|
||||
// @TODO: Restoring Application State
|
||||
// Depends on NSCoder support, which is... welp.
|
||||
|
||||
// Scripting
|
||||
decl.add_method(
|
||||
sel!(application:delegateHandlesKey:),
|
||||
delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
// Scripting
|
||||
decl.add_method(
|
||||
sel!(application:delegateHandlesKey:),
|
||||
delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { DELEGATE_CLASS }
|
||||
}
|
||||
|
|
|
@ -316,17 +316,22 @@ extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) {
|
|||
pub(crate) fn register_menu_item_class() -> *const Class {
|
||||
static mut APP_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "CacaoMenuItem";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSMenuItem);
|
||||
let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap();
|
||||
decl.add_ivar::<usize>(BLOCK_PTR);
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { APP_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSMenuItem);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
decl.add_ivar::<usize>(BLOCK_PTR);
|
||||
|
||||
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
|
||||
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
|
||||
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { APP_CLASS }
|
||||
}
|
||||
|
|
|
@ -14,13 +14,18 @@ use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
|
|||
pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class {
|
||||
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTWindowController";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSWindowController);
|
||||
let mut decl = ClassDecl::new("RSTWindowController", superclass).unwrap();
|
||||
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { DELEGATE_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSWindowController);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { DELEGATE_CLASS }
|
||||
}
|
||||
|
|
|
@ -345,12 +345,18 @@ impl Drop for Button {
|
|||
fn register_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTButton";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSButton);
|
||||
let decl = ClassDecl::new("RSTButton", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe {
|
||||
VIEW_CLASS = c;
|
||||
}
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSButton);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -261,107 +261,112 @@ extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger)
|
|||
pub(crate) fn register_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "CacaoDynamicColor";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSColor);
|
||||
let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSColor);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
// 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!(colorUsingColorSpace:),
|
||||
color_using_color_space as extern "C" fn(&Object, _, id) -> id
|
||||
);
|
||||
decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id);
|
||||
decl.add_method(
|
||||
sel!(colorUsingColorSpaceName:),
|
||||
color_using_color_space_name as extern "C" fn(&Object, _, id) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(numberOfComponents),
|
||||
number_of_components as extern "C" fn(&Object, _) -> NSInteger
|
||||
);
|
||||
// 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!(colorUsingColorSpace:),
|
||||
color_using_color_space as extern "C" fn(&Object, _, id) -> id
|
||||
);
|
||||
decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id);
|
||||
decl.add_method(
|
||||
sel!(colorUsingColorSpaceName:),
|
||||
color_using_color_space_name as extern "C" fn(&Object, _, id) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(numberOfComponents),
|
||||
number_of_components as extern "C" fn(&Object, _) -> NSInteger
|
||||
);
|
||||
|
||||
decl.add_method(sel!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat));
|
||||
decl.add_method(
|
||||
sel!(getRed:green:blue:alpha:),
|
||||
get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
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!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat));
|
||||
decl.add_method(
|
||||
sel!(getRed:green:blue:alpha:),
|
||||
get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
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!(saturationComponent),
|
||||
saturation_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(brightnessComponent),
|
||||
brightness_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(getHue:saturation:brightness:alpha:),
|
||||
get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
decl.add_method(sel!(hueComponent), hue_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
decl.add_method(
|
||||
sel!(saturationComponent),
|
||||
saturation_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(brightnessComponent),
|
||||
brightness_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(getHue:saturation:brightness:alpha:),
|
||||
get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
|
||||
decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
decl.add_method(
|
||||
sel!(getWhite:alpha:),
|
||||
get_white as extern "C" fn(&Object, _, CGFloat, CGFloat)
|
||||
);
|
||||
decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
decl.add_method(
|
||||
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!(magentaComponent),
|
||||
magenta_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
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(
|
||||
sel!(getCyan:magenta:yellow:black:alpha:),
|
||||
get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
decl.add_method(
|
||||
sel!(magentaComponent),
|
||||
magenta_component as extern "C" fn(&Object, _) -> CGFloat
|
||||
);
|
||||
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(
|
||||
sel!(getCyan:magenta:yellow:black:alpha:),
|
||||
get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat)
|
||||
);
|
||||
|
||||
decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(&Object, _) -> CGFloat);
|
||||
|
||||
decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id);
|
||||
decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id);
|
||||
decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _));
|
||||
|
||||
decl.add_method(
|
||||
sel!(highlightWithLevel:),
|
||||
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(
|
||||
sel!(highlightWithLevel:),
|
||||
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(
|
||||
sel!(colorWithAlphaComponent:),
|
||||
color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(blendedColorWithFraction:ofColor:),
|
||||
blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(colorWithSystemEffect:),
|
||||
color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(colorWithAlphaComponent:),
|
||||
color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(blendedColorWithFraction:ofColor:),
|
||||
blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(colorWithSystemEffect:),
|
||||
color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id
|
||||
);
|
||||
|
||||
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST);
|
||||
decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -25,15 +25,20 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
|
|||
pub(crate) fn register_image_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTImageView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSImageView);
|
||||
let decl = ClassDecl::new("RSTImageView", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSImageView);
|
||||
let decl = ClassDecl::new(CLASS_NAME, 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(&Object, _) -> BOOL);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -15,12 +15,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
|
|||
pub(crate) fn register_image_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTImageView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIImageView);
|
||||
let mut decl = ClassDecl::new("RSTImageView", superclass).expect("Failed to get RSTVIEW");
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIImageView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).expect("Failed to get RSTVIEW");
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -54,12 +54,17 @@ extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _
|
|||
pub(crate) fn register_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTTextInputField";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTextField);
|
||||
let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTextField);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -97,16 +97,23 @@ extern "C" fn perform<F: Fn() + 'static>(this: &mut Object, _: Sel, _sender: id)
|
|||
pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTTargetActionHandler";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe {
|
||||
VIEW_CLASS = c;
|
||||
}
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
|
||||
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
|
||||
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
|
||||
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -187,12 +187,17 @@ extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, in
|
|||
pub(crate) fn register_listview_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &'static str = "RSTListView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTableView);
|
||||
let decl = ClassDecl::new("RSTListView", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTableView);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -109,15 +109,20 @@ extern "C" fn dealloc<T: ViewDelegate>(this: &Object, _: Sel) {
|
|||
pub(crate) fn register_listview_row_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTTableViewRow";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new("RSTTableViewRow", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, 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(&Object, _) -> BOOL);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
@ -127,46 +132,51 @@ pub(crate) fn register_listview_row_class() -> *const Class {
|
|||
pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTableViewRowWithDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new("RSTableViewRowWithDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR);
|
||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR);
|
||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||
|
||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
||||
|
||||
// Drag and drop operations (e.g, accepting files)
|
||||
decl.add_method(
|
||||
sel!(draggingEntered:),
|
||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(prepareForDragOperation:),
|
||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(performDragOperation:),
|
||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(concludeDragOperation:),
|
||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(draggingExited:),
|
||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
// Drag and drop operations (e.g, accepting files)
|
||||
decl.add_method(
|
||||
sel!(draggingEntered:),
|
||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(prepareForDragOperation:),
|
||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(performDragOperation:),
|
||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(concludeDragOperation:),
|
||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(draggingExited:),
|
||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
|
||||
// Cleanup
|
||||
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _));
|
||||
// Cleanup
|
||||
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _));
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -16,12 +16,17 @@ use crate::utils::load;
|
|||
pub(crate) fn register_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
@ -31,15 +36,18 @@ pub(crate) fn register_view_class() -> *const Class {
|
|||
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTViewWithDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap();
|
||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
|
||||
unsafe {
|
||||
VIEW_CLASS
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -79,12 +79,17 @@ extern "C" fn dragging_exited<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
|
|||
pub(crate) fn register_scrollview_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &'static str = "RSTScrollView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSScrollView);
|
||||
let decl = ClassDecl::new("RSTScrollView", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSScrollView);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
@ -94,41 +99,46 @@ pub(crate) fn register_scrollview_class() -> *const Class {
|
|||
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &'static str = "RSTScrollViewWithDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSScrollView);
|
||||
let mut decl = ClassDecl::new("RSTScrollViewWithDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSScrollView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
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(&Object, _) -> BOOL);
|
||||
|
||||
// Drag and drop operations (e.g, accepting files)
|
||||
decl.add_method(
|
||||
sel!(draggingEntered:),
|
||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(prepareForDragOperation:),
|
||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(performDragOperation:),
|
||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(concludeDragOperation:),
|
||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(draggingExited:),
|
||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
// Drag and drop operations (e.g, accepting files)
|
||||
decl.add_method(
|
||||
sel!(draggingEntered:),
|
||||
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(prepareForDragOperation:),
|
||||
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(performDragOperation:),
|
||||
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(concludeDragOperation:),
|
||||
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(draggingExited:),
|
||||
dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
|
||||
);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -270,12 +270,17 @@ impl Drop for Select {
|
|||
fn register_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "CacaoSelect";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSPopUpButton);
|
||||
let decl = ClassDecl::new("CacaoSelect", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSPopUpButton);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -180,12 +180,19 @@ impl Drop for Switch {
|
|||
fn register_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTSwitch";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSButton);
|
||||
let decl = ClassDecl::new("RSTSwitch", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe {
|
||||
VIEW_CLASS = c;
|
||||
}
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSButton);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -25,12 +25,17 @@ use crate::utils::load;
|
|||
pub(crate) fn register_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTTextField";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTextField);
|
||||
let decl = ClassDecl::new("RSTTextField", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSTextField);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
@ -40,17 +45,22 @@ pub(crate) fn register_view_class() -> *const Class {
|
|||
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTTextFieldWithDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new("RSTTextFieldWithDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
|
||||
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't
|
||||
// move.
|
||||
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -12,12 +12,17 @@ use objc::runtime::Class;
|
|||
pub(crate) fn register_app_class() -> *const Class {
|
||||
static mut APP_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTApplication";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIApplication);
|
||||
let decl = ClassDecl::new("RSTApplication", superclass).unwrap();
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { APP_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIApplication);
|
||||
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
APP_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { APP_CLASS }
|
||||
}
|
||||
|
|
|
@ -51,29 +51,34 @@ extern "C" fn configuration_for_scene_session<T: AppDelegate>(this: &Object, _:
|
|||
pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class {
|
||||
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTAppDelegate";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { DELEGATE_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
// Launching Applications
|
||||
decl.add_method(
|
||||
sel!(application:didFinishLaunchingWithOptions:),
|
||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
// Launching Applications
|
||||
decl.add_method(
|
||||
sel!(application:didFinishLaunchingWithOptions:),
|
||||
did_finish_launching::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
|
||||
);
|
||||
|
||||
// Scenes
|
||||
decl.add_method(
|
||||
sel!(application:configurationForConnectingSceneSession:options:),
|
||||
configuration_for_scene_session::<T> as extern "C" fn(&Object, _, _, id, id) -> id
|
||||
);
|
||||
/*decl.add_method(
|
||||
sel!(application:didDiscardSceneSessions:),
|
||||
did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);*/
|
||||
// Scenes
|
||||
decl.add_method(
|
||||
sel!(application:configurationForConnectingSceneSession:options:),
|
||||
configuration_for_scene_session::<T> as extern "C" fn(&Object, _, _, id, id) -> id
|
||||
);
|
||||
/*decl.add_method(
|
||||
sel!(application:didDiscardSceneSessions:),
|
||||
did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id)
|
||||
);*/
|
||||
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { DELEGATE_CLASS }
|
||||
}
|
||||
|
|
|
@ -62,30 +62,35 @@ extern "C" fn scene_will_connect_to_session_with_options<T: WindowSceneDelegate>
|
|||
pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class {
|
||||
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTWindowSceneDelegate";
|
||||
|
||||
use objc::runtime::{class_addProtocol, Protocol};
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIResponder);
|
||||
let mut decl = ClassDecl::new("RSTWindowSceneDelegate", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { DELEGATE_CLASS = c };
|
||||
} else {
|
||||
use objc::runtime::Protocol;
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIResponder);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
let p = Protocol::get("UIWindowSceneDelegate").unwrap();
|
||||
let p = Protocol::get("UIWindowSceneDelegate").unwrap();
|
||||
|
||||
// A spot to hold a pointer to
|
||||
decl.add_ivar::<usize>(WINDOW_SCENE_PTR);
|
||||
decl.add_protocol(p);
|
||||
// A spot to hold a pointer to
|
||||
decl.add_ivar::<usize>(WINDOW_SCENE_PTR);
|
||||
decl.add_protocol(p);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
|
||||
// UIWindowSceneDelegate API
|
||||
decl.add_method(
|
||||
sel!(scene:willConnectToSession:options:),
|
||||
scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _)
|
||||
);
|
||||
// UIWindowSceneDelegate API
|
||||
decl.add_method(
|
||||
sel!(scene:willConnectToSession:options:),
|
||||
scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _)
|
||||
);
|
||||
|
||||
// Launching Applications
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
// Launching Applications
|
||||
DELEGATE_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { DELEGATE_CLASS }
|
||||
}
|
||||
|
|
|
@ -94,19 +94,24 @@ extern "C" fn update_layer(this: &Object, _: Sel) {
|
|||
pub(crate) fn register_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(NSView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
|
||||
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
|
||||
|
||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||
decl.add_ivar::<id>(BACKGROUND_COLOR);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -53,20 +53,30 @@ extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated
|
|||
pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTViewController";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIViewController);
|
||||
let mut decl = ClassDecl::new("RSTViewController", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIViewController);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
|
||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
|
||||
|
||||
decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
decl.add_method(sel!(viewWillDisappear:), will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
decl.add_method(sel!(viewDidDisappear:), did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
|
||||
decl.add_method(
|
||||
sel!(viewWillDisappear:),
|
||||
will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(viewDidDisappear:),
|
||||
did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
|
||||
);
|
||||
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -16,12 +16,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
|
|||
pub(crate) fn register_view_class() -> *const Class {
|
||||
static mut VIEW_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTView";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { VIEW_CLASS = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = class!(UIView);
|
||||
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
|
||||
VIEW_CLASS = decl.register();
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { VIEW_CLASS }
|
||||
}
|
||||
|
|
|
@ -28,17 +28,22 @@ extern "C" fn download_delegate(this: &Object, _: Sel) -> id {
|
|||
pub fn register_process_pool() -> *const Object {
|
||||
static mut PROCESS_POOL: *const Object = 0 as *const Object;
|
||||
static INIT: Once = Once::new();
|
||||
const CLASS_NAME: &str = "RSTWebViewProcessPool";
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = Class::get("WKProcessPool").unwrap();
|
||||
let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap();
|
||||
if let Some(c) = Class::get(CLASS_NAME) {
|
||||
unsafe { PROCESS_POOL = c };
|
||||
} else {
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = Class::get("WKProcessPool").unwrap();
|
||||
let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap();
|
||||
|
||||
//decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR);
|
||||
decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id);
|
||||
//decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR);
|
||||
decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id);
|
||||
|
||||
//PROCESS_POOL = decl.register();
|
||||
PROCESS_POOL = msg_send![decl.register(), new];
|
||||
});
|
||||
//PROCESS_POOL = decl.register();
|
||||
PROCESS_POOL = msg_send![decl.register(), new];
|
||||
});
|
||||
}
|
||||
|
||||
unsafe { PROCESS_POOL }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue