Merge pull request #29

Merge `cargo fmt` work from @madsmtm (https://github.com/ryanmcgrath/cacao/pull/29).

See context for merge oddities here: https://github.com/ryanmcgrath/cacao/pull/33
This commit is contained in:
Ryan McGrath 2022-07-17 23:30:30 -07:00 committed by GitHub
commit 0294647683
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
177 changed files with 2819 additions and 2686 deletions

23
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: CI
on:
push:
branches: [master]
pull_request:
jobs:
fmt:
name: Check formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
override: true
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: -- --check

View file

@ -360,7 +360,7 @@ pub(crate) fn register_view_class() -> *const Class {
let superclass = class!(NSView); let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
decl.add_ivar::<id>(BACKGROUND_COLOR); decl.add_ivar::<id>(BACKGROUND_COLOR);
@ -384,12 +384,12 @@ pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>(instance: &T) -
decl.add_method( decl.add_method(
sel!(isFlipped), sel!(isFlipped),
enforce_normalcy as extern fn(&Object, _) -> BOOL enforce_normalcy as extern "C" fn(&Object, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(draggingEntered:), sel!(draggingEntered:),
dragging_entered::<T> as extern fn (&mut Object, _, _) -> NSUInteger dragging_entered::<T> as extern "C" fn (&mut Object, _, _) -> NSUInteger
); );
}) })
} }
@ -401,7 +401,7 @@ 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 fn is_flipped(_: &Object, _: Sel) -> BOOL { extern "C" fn is_flipped(_: &Object, _: Sel) -> BOOL {
return YES; return YES;
} }
``` ```
@ -409,7 +409,7 @@ extern fn is_flipped(_: &Object, _: Sel) -> BOOL {
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 `YES` in this subclass method.
``` rust ``` rust
extern 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::from_ptr(info) }

View file

@ -9,10 +9,10 @@ use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint, LayoutConstraintAnimatorProxy}; use cacao::layout::{Layout, LayoutConstraint, LayoutConstraintAnimatorProxy};
use cacao::view::{View, ViewAnimatorProxy}; use cacao::view::{View, ViewAnimatorProxy};
use cacao::appkit::{App, AppDelegate, AnimationContext};
use cacao::appkit::{Event, EventMask, EventMonitor};
use cacao::appkit::menu::Menu; use cacao::appkit::menu::Menu;
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
use cacao::appkit::{AnimationContext, App, AppDelegate};
use cacao::appkit::{Event, EventMask, EventMonitor};
struct BasicApp { struct BasicApp {
window: Window<AppWindow> window: Window<AppWindow>
@ -54,33 +54,26 @@ const ANIMATIONS: [[[f64; 5]; 4]; 3] = [
[44., 16., 100., 100., 1.], [44., 16., 100., 100., 1.],
[128., 84., 144., 124., 1.], [128., 84., 144., 124., 1.],
[32., 32., 44., 44., 0.7], [32., 32., 44., 44., 0.7],
[328., 157., 200., 200., 0.7], [328., 157., 200., 200., 0.7]
], ],
// Red // Red
[ [
[44., 132., 100., 100., 1.], [44., 132., 100., 100., 1.],
[40., 47., 80., 64., 0.7], [40., 47., 80., 64., 0.7],
[84., 220., 600., 109., 1.0], [84., 220., 600., 109., 1.0],
[48., 600., 340., 44., 0.7], [48., 600., 340., 44., 0.7]
], ],
// Green // Green
[ [
[44., 248., 100., 100., 1.], [44., 248., 100., 100., 1.],
[420., 232., 420., 244., 0.7], [420., 232., 420., 244., 0.7],
[310., 440., 150., 238., 0.7], [310., 440., 150., 238., 0.7],
[32., 32., 44., 44., 1.], [32., 32., 44., 44., 1.]
] ]
]; ];
/// A helper method for generating frame constraints that we want to be animating. /// A helper method for generating frame constraints that we want to be animating.
fn apply_styles( fn apply_styles(view: &View, parent: &View, background_color: Color, animation_table_index: usize) -> [LayoutConstraint; 4] {
view: &View,
parent: &View,
background_color: Color,
animation_table_index: usize
) -> [LayoutConstraint; 4] {
view.set_background_color(background_color); view.set_background_color(background_color);
view.layer.set_corner_radius(16.); view.layer.set_corner_radius(16.);
parent.add_subview(view); parent.add_subview(view);
@ -117,11 +110,14 @@ impl WindowDelegate for AppWindow {
let red_frame = apply_styles(&self.red, &self.content, Color::SystemRed, 1); let red_frame = apply_styles(&self.red, &self.content, Color::SystemRed, 1);
let green_frame = apply_styles(&self.green, &self.content, Color::SystemGreen, 2); let green_frame = apply_styles(&self.green, &self.content, Color::SystemGreen, 2);
let alpha_animators = [&self.blue, &self.red, &self.green].iter().map(|view| { let alpha_animators = [&self.blue, &self.red, &self.green]
view.animator.clone() .iter()
}).collect::<Vec<ViewAnimatorProxy>>(); .map(|view| view.animator.clone())
.collect::<Vec<ViewAnimatorProxy>>();
let constraint_animators = [blue_frame, red_frame, green_frame].iter().map(|frame| { let constraint_animators = [blue_frame, red_frame, green_frame]
.iter()
.map(|frame| {
LayoutConstraint::activate(frame); LayoutConstraint::activate(frame);
vec![ vec![
@ -130,7 +126,8 @@ impl WindowDelegate for AppWindow {
frame[2].animator.clone(), frame[2].animator.clone(),
frame[3].animator.clone(), frame[3].animator.clone(),
] ]
}).collect::<Vec<Vec<LayoutConstraintAnimatorProxy>>>(); })
.collect::<Vec<Vec<LayoutConstraintAnimatorProxy>>>();
// Monitor key change events for w/a/s/d, and then animate each view to their correct // Monitor key change events for w/a/s/d, and then animate each view to their correct
// frame and alpha value. // frame and alpha value.
@ -175,5 +172,6 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with(WindowConfig::default(), AppWindow::default()) window: Window::with(WindowConfig::default(), AppWindow::default())
}).run(); })
.run();
} }

View file

@ -5,9 +5,9 @@ use cacao::color::{Color, Theme};
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::view::View; use cacao::view::View;
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
use cacao::appkit::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: Window<AppWindow> window: Window<AppWindow>
@ -23,23 +23,16 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![ Menu::new("View", vec![MenuItem::EnterFullScreen]),
MenuItem::CloseWindow
]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
]); ]);
App::activate(); App::activate();
@ -89,16 +82,14 @@ impl WindowDelegate for AppWindow {
self.blue.leading.constraint_equal_to(&self.content.leading).offset(16.), self.blue.leading.constraint_equal_to(&self.content.leading).offset(16.),
self.blue.bottom.constraint_equal_to(&self.content.bottom).offset(-16.), self.blue.bottom.constraint_equal_to(&self.content.bottom).offset(-16.),
self.blue.width.constraint_equal_to_constant(100.), self.blue.width.constraint_equal_to_constant(100.),
self.red.top.constraint_equal_to(&self.content.top).offset(46.), self.red.top.constraint_equal_to(&self.content.top).offset(46.),
self.red.leading.constraint_equal_to(&self.blue.trailing).offset(16.), self.red.leading.constraint_equal_to(&self.blue.trailing).offset(16.),
self.red.bottom.constraint_equal_to(&self.content.bottom).offset(-16.), self.red.bottom.constraint_equal_to(&self.content.bottom).offset(-16.),
self.green.top.constraint_equal_to(&self.content.top).offset(46.), self.green.top.constraint_equal_to(&self.content.top).offset(46.),
self.green.leading.constraint_equal_to(&self.red.trailing).offset(16.), self.green.leading.constraint_equal_to(&self.red.trailing).offset(16.),
self.green.trailing.constraint_equal_to(&self.content.trailing).offset(-16.), self.green.trailing.constraint_equal_to(&self.content.trailing).offset(-16.),
self.green.bottom.constraint_equal_to(&self.content.bottom).offset(-16.), self.green.bottom.constraint_equal_to(&self.content.bottom).offset(-16.),
self.green.width.constraint_equal_to_constant(100.), self.green.width.constraint_equal_to_constant(100.)
]); ]);
} }
} }
@ -106,5 +97,6 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with(WindowConfig::default(), AppWindow::default()) window: Window::with(WindowConfig::default(), AppWindow::default())
}).run(); })
.run();
} }

View file

@ -4,10 +4,10 @@
use cacao::notification_center::Dispatcher; use cacao::notification_center::Dispatcher;
use cacao::webview::{WebView, WebViewConfig, WebViewDelegate}; use cacao::webview::{WebView, WebViewConfig, WebViewDelegate};
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::toolbar::Toolbar; use cacao::appkit::toolbar::Toolbar;
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle};
use cacao::appkit::{App, AppDelegate};
mod toolbar; mod toolbar;
use toolbar::BrowserToolbar; use toolbar::BrowserToolbar;
@ -39,13 +39,9 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![
MenuItem::CloseWindow
]),
Menu::new("Edit", vec![ Menu::new("Edit", vec![
MenuItem::Undo, MenuItem::Undo,
MenuItem::Redo, MenuItem::Redo,
@ -54,21 +50,16 @@ impl AppDelegate for BasicApp {
MenuItem::Copy, MenuItem::Copy,
MenuItem::Paste, MenuItem::Paste,
MenuItem::Separator, MenuItem::Separator,
MenuItem::SelectAll MenuItem::SelectAll,
]), ]),
Menu::new("View", vec![MenuItem::EnterFullScreen]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]), ]),
Menu::new("Help", vec![]),
Menu::new("Help", vec![])
]); ]);
App::activate(); App::activate();
@ -84,9 +75,15 @@ impl Dispatcher for BasicApp {
let webview = &window.content; let webview = &window.content;
match message { match message {
Action::Back => { webview.go_back(); }, Action::Back => {
Action::Forwards => { webview.go_forward(); }, webview.go_back();
Action::Load(url) => { window.load_url(&url); } },
Action::Forwards => {
webview.go_forward();
},
Action::Load(url) => {
window.load_url(&url);
}
} }
} }
} }
@ -132,13 +129,17 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with({ window: Window::with(
{
let mut config = WindowConfig::default(); let mut config = WindowConfig::default();
// This flag is necessary for Big Sur to use the correct toolbar style. // This flag is necessary for Big Sur to use the correct toolbar style.
config.toolbar_style = WindowToolbarStyle::Expanded; config.toolbar_style = WindowToolbarStyle::Expanded;
config config
}, AppWindow::new()) },
}).run(); AppWindow::new()
)
})
.run();
} }

View file

@ -1,10 +1,9 @@
use cacao::objc::{msg_send, sel, sel_impl}; use cacao::objc::{msg_send, sel, sel_impl};
use cacao::button::Button; use cacao::button::Button;
use cacao::input::{TextField, TextFieldDelegate}; use cacao::input::{TextField, TextFieldDelegate};
use cacao::appkit::toolbar::{Toolbar, ToolbarDisplayMode, ToolbarItem, ItemIdentifier, ToolbarDelegate}; use cacao::appkit::toolbar::{ItemIdentifier, Toolbar, ToolbarDelegate, ToolbarDisplayMode, ToolbarItem};
use super::Action; use super::Action;
@ -74,7 +73,7 @@ impl BrowserToolbar {
ItemIdentifier::Custom(FWDS_BUTTON), ItemIdentifier::Custom(FWDS_BUTTON),
ItemIdentifier::Space, ItemIdentifier::Space,
ItemIdentifier::Custom(URL_BAR), ItemIdentifier::Custom(URL_BAR),
ItemIdentifier::Space ItemIdentifier::Space,
] ]
} }
} }
@ -99,7 +98,9 @@ impl ToolbarDelegate for BrowserToolbar {
BACK_BUTTON => &self.back_item, BACK_BUTTON => &self.back_item,
FWDS_BUTTON => &self.forwards_item, FWDS_BUTTON => &self.forwards_item,
URL_BAR => &self.url_bar_item, URL_BAR => &self.url_bar_item,
_ => { std::unreachable!(); } _ => {
std::unreachable!();
}
} }
} }
} }

View file

@ -1,10 +1,10 @@
use cacao::layout::{LayoutConstraint, Layout};
use cacao::button::Button; use cacao::button::Button;
use cacao::color::Color; use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint};
use cacao::view::View; use cacao::view::View;
use crate::calculator::Msg; use crate::calculator::Msg;
use crate::content_view::{button, BUTTON_WIDTH, BUTTON_HEIGHT}; use crate::content_view::{button, BUTTON_HEIGHT, BUTTON_WIDTH};
pub struct ButtonRow { pub struct ButtonRow {
pub view: View, pub view: View,
@ -15,8 +15,11 @@ impl ButtonRow {
pub fn new(x: [Msg; 4], color: Color, action_color: Color) -> Self { pub fn new(x: [Msg; 4], color: Color, action_color: Color) -> Self {
let view = View::new(); let view = View::new();
let buttons: Vec<Button> = x.iter().map(|y| { let buttons: Vec<Button> = x
let button = button(match y { .iter()
.map(|y| {
let button = button(
match y {
Msg::Clear => "C", Msg::Clear => "C",
Msg::Add => "+", Msg::Add => "+",
Msg::Subtract => "-", Msg::Subtract => "-",
@ -34,12 +37,14 @@ impl ButtonRow {
Msg::Push(i) if *i == 8 => "8", Msg::Push(i) if *i == 8 => "8",
Msg::Push(i) if *i == 9 => "9", Msg::Push(i) if *i == 9 => "9",
_ => "W" _ => "W"
},
}, y.clone()); y.clone()
);
view.add_subview(&button); view.add_subview(&button);
button button
}).collect(); })
.collect();
buttons[0].set_background_color(color.clone()); buttons[0].set_background_color(color.clone());
buttons[1].set_background_color(color.clone()); buttons[1].set_background_color(color.clone());
@ -53,30 +58,22 @@ impl ButtonRow {
buttons[0].leading.constraint_equal_to(&view.leading), buttons[0].leading.constraint_equal_to(&view.leading),
buttons[0].bottom.constraint_equal_to(&view.bottom), buttons[0].bottom.constraint_equal_to(&view.bottom),
width.constraint_equal_to_constant(BUTTON_WIDTH), width.constraint_equal_to_constant(BUTTON_WIDTH),
buttons[1].top.constraint_equal_to(&view.top), buttons[1].top.constraint_equal_to(&view.top),
buttons[1].leading.constraint_equal_to(&buttons[0].trailing).offset(1.), buttons[1].leading.constraint_equal_to(&buttons[0].trailing).offset(1.),
buttons[1].bottom.constraint_equal_to(&view.bottom), buttons[1].bottom.constraint_equal_to(&view.bottom),
buttons[1].width.constraint_equal_to(&width), buttons[1].width.constraint_equal_to(&width),
buttons[2].top.constraint_equal_to(&view.top), buttons[2].top.constraint_equal_to(&view.top),
buttons[2].leading.constraint_equal_to(&buttons[1].trailing).offset(1.), buttons[2].leading.constraint_equal_to(&buttons[1].trailing).offset(1.),
buttons[2].bottom.constraint_equal_to(&view.bottom), buttons[2].bottom.constraint_equal_to(&view.bottom),
buttons[2].width.constraint_equal_to(&width), buttons[2].width.constraint_equal_to(&width),
buttons[3].top.constraint_equal_to(&view.top), buttons[3].top.constraint_equal_to(&view.top),
buttons[3].leading.constraint_equal_to(&buttons[2].trailing).offset(1.), buttons[3].leading.constraint_equal_to(&buttons[2].trailing).offset(1.),
buttons[3].trailing.constraint_equal_to(&view.trailing), buttons[3].trailing.constraint_equal_to(&view.trailing),
buttons[3].bottom.constraint_equal_to(&view.bottom), buttons[3].bottom.constraint_equal_to(&view.bottom),
buttons[3].width.constraint_equal_to(&width), buttons[3].width.constraint_equal_to(&width),
view.height.constraint_equal_to_constant(BUTTON_HEIGHT) view.height.constraint_equal_to_constant(BUTTON_HEIGHT)
]); ]);
Self { Self { view, buttons }
view,
buttons
}
} }
} }

View file

@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use cacao::lazy_static::lazy_static;
use cacao::appkit::App; use cacao::appkit::App;
use cacao::lazy_static::lazy_static;
use crate::CalculatorApp; use crate::CalculatorApp;
@ -92,10 +92,14 @@ impl Calculator {
println!("Expr: {}", expr); println!("Expr: {}", expr);
match eval::eval(&expr) { match eval::eval(&expr) {
Ok(val) => { App::<CalculatorApp, String>::dispatch_main(val.to_string()); }, Ok(val) => {
Err(e) => { eprintln!("Error parsing expression: {:?}", e); } App::<CalculatorApp, String>::dispatch_main(val.to_string());
},
Err(e) => {
eprintln!("Error parsing expression: {:?}", e);
} }
} }
},
_ => {} _ => {}
} }

View file

@ -1,8 +1,8 @@
use cacao::text::{Font, Label, TextAlign};
use cacao::layout::{LayoutConstraint, Layout};
use cacao::button::{Button, BezelStyle};
use cacao::color::Color;
use cacao::appkit::FocusRingType; use cacao::appkit::FocusRingType;
use cacao::button::{BezelStyle, Button};
use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint};
use cacao::text::{Font, Label, TextAlign};
use cacao::view::{View, ViewDelegate}; use cacao::view::{View, ViewDelegate};
use crate::button_row::ButtonRow; use crate::button_row::ButtonRow;
@ -53,21 +53,29 @@ impl CalculatorView {
results_wrapper, results_wrapper,
label, label,
row0: ButtonRow::new([ row0: ButtonRow::new(
Msg::Clear, Msg::Invert, Msg::Mod, Msg::Divide [Msg::Clear, Msg::Invert, Msg::Mod, Msg::Divide],
], Color::rgb(69, 69, 69), Color::rgb(255, 148, 10)), Color::rgb(69, 69, 69),
Color::rgb(255, 148, 10)
),
row1: ButtonRow::new([ row1: ButtonRow::new(
Msg::Push(7), Msg::Push(8), Msg::Push(9), Msg::Multiply [Msg::Push(7), Msg::Push(8), Msg::Push(9), Msg::Multiply],
], Color::rgb(100, 100, 100), Color::rgb(255, 148, 10)), Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
row2: ButtonRow::new([ row2: ButtonRow::new(
Msg::Push(4), Msg::Push(5), Msg::Push(6), Msg::Subtract [Msg::Push(4), Msg::Push(5), Msg::Push(6), Msg::Subtract],
], Color::rgb(100, 100, 100), Color::rgb(255, 148, 10)), Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
row3: ButtonRow::new([ row3: ButtonRow::new(
Msg::Push(1), Msg::Push(2), Msg::Push(3), Msg::Add [Msg::Push(1), Msg::Push(2), Msg::Push(3), Msg::Add],
], Color::rgb(100, 100, 100), Color::rgb(255, 148, 10)), Color::rgb(100, 100, 100),
Color::rgb(255, 148, 10)
),
zero: button("0", Msg::Push(0)), zero: button("0", Msg::Push(0)),
dot: button(".", Msg::Decimal), dot: button(".", Msg::Decimal),
@ -108,38 +116,43 @@ impl ViewDelegate for CalculatorView {
self.results_wrapper.leading.constraint_equal_to(&view.leading), self.results_wrapper.leading.constraint_equal_to(&view.leading),
self.results_wrapper.trailing.constraint_equal_to(&view.trailing), self.results_wrapper.trailing.constraint_equal_to(&view.trailing),
self.results_wrapper.height.constraint_equal_to_constant(80.), self.results_wrapper.height.constraint_equal_to_constant(80.),
self.label
self.label.leading.constraint_equal_to(&self.results_wrapper.leading).offset(22.), .leading
self.label.trailing.constraint_equal_to(&self.results_wrapper.trailing).offset(-16.), .constraint_equal_to(&self.results_wrapper.leading)
self.label.bottom.constraint_equal_to(&self.results_wrapper.bottom).offset(-4.), .offset(22.),
self.label
.trailing
.constraint_equal_to(&self.results_wrapper.trailing)
.offset(-16.),
self.label
.bottom
.constraint_equal_to(&self.results_wrapper.bottom)
.offset(-4.),
// Buttons laid out from top-left // Buttons laid out from top-left
self.row0.view.top.constraint_equal_to(&self.results_wrapper.bottom).offset(1.), self.row0
.view
.top
.constraint_equal_to(&self.results_wrapper.bottom)
.offset(1.),
self.row0.view.leading.constraint_equal_to(&view.leading), self.row0.view.leading.constraint_equal_to(&view.leading),
self.row0.view.trailing.constraint_equal_to(&view.trailing), self.row0.view.trailing.constraint_equal_to(&view.trailing),
self.row1.view.top.constraint_equal_to(&self.row0.view.bottom).offset(1.), self.row1.view.top.constraint_equal_to(&self.row0.view.bottom).offset(1.),
self.row1.view.leading.constraint_equal_to(&view.leading), self.row1.view.leading.constraint_equal_to(&view.leading),
self.row1.view.trailing.constraint_equal_to(&view.trailing), self.row1.view.trailing.constraint_equal_to(&view.trailing),
self.row2.view.top.constraint_equal_to(&self.row1.view.bottom).offset(1.), self.row2.view.top.constraint_equal_to(&self.row1.view.bottom).offset(1.),
self.row2.view.leading.constraint_equal_to(&view.leading), self.row2.view.leading.constraint_equal_to(&view.leading),
self.row2.view.trailing.constraint_equal_to(&view.trailing), self.row2.view.trailing.constraint_equal_to(&view.trailing),
self.row3.view.top.constraint_equal_to(&self.row2.view.bottom).offset(1.), self.row3.view.top.constraint_equal_to(&self.row2.view.bottom).offset(1.),
self.row3.view.leading.constraint_equal_to(&view.leading), self.row3.view.leading.constraint_equal_to(&view.leading),
self.row3.view.trailing.constraint_equal_to(&view.trailing), self.row3.view.trailing.constraint_equal_to(&view.trailing),
self.zero.top.constraint_equal_to(&self.row3.view.bottom).offset(1.), self.zero.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.zero.leading.constraint_equal_to(&view.leading), self.zero.leading.constraint_equal_to(&view.leading),
self.zero.bottom.constraint_equal_to(&view.bottom), self.zero.bottom.constraint_equal_to(&view.bottom),
self.dot.top.constraint_equal_to(&self.row3.view.bottom).offset(1.), self.dot.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.dot.leading.constraint_equal_to(&self.zero.trailing).offset(1.), self.dot.leading.constraint_equal_to(&self.zero.trailing).offset(1.),
self.dot.bottom.constraint_equal_to(&view.bottom), self.dot.bottom.constraint_equal_to(&view.bottom),
self.dot.width.constraint_equal_to_constant(BUTTON_WIDTH), self.dot.width.constraint_equal_to_constant(BUTTON_WIDTH),
self.dot.height.constraint_equal_to_constant(BUTTON_HEIGHT), self.dot.height.constraint_equal_to_constant(BUTTON_HEIGHT),
self.equals.top.constraint_equal_to(&self.row3.view.bottom).offset(1.), self.equals.top.constraint_equal_to(&self.row3.view.bottom).offset(1.),
self.equals.leading.constraint_equal_to(&self.dot.trailing).offset(1.), self.equals.leading.constraint_equal_to(&self.dot.trailing).offset(1.),
self.equals.trailing.constraint_equal_to(&view.trailing), self.equals.trailing.constraint_equal_to(&view.trailing),

View file

@ -11,8 +11,8 @@
use std::sync::RwLock; use std::sync::RwLock;
use cacao::appkit::window::{TitleVisibility, Window, WindowConfig};
use cacao::appkit::{App, AppDelegate}; use cacao::appkit::{App, AppDelegate};
use cacao::appkit::window::{Window, WindowConfig, TitleVisibility};
use cacao::appkit::{Event, EventMask, EventMonitor}; use cacao::appkit::{Event, EventMask, EventMonitor};
use cacao::color::Color; use cacao::color::Color;
use cacao::notification_center::Dispatcher; use cacao::notification_center::Dispatcher;
@ -40,7 +40,7 @@ impl AppDelegate for CalculatorApp {
//self.start_monitoring(); //self.start_monitoring();
self.window.set_title("Calculator"); self.window.set_title("Calculator");
self.window.set_background_color(Color::rgb(49,49,49)); self.window.set_background_color(Color::rgb(49, 49, 49));
self.window.set_title_visibility(TitleVisibility::Hidden); self.window.set_title_visibility(TitleVisibility::Hidden);
self.window.set_titlebar_appears_transparent(true); self.window.set_titlebar_appears_transparent(true);
self.window.set_movable_by_background(true); self.window.set_movable_by_background(true);
@ -109,5 +109,6 @@ fn main() {
window: Window::new(config), window: Window::new(config),
content: View::with(CalculatorView::new()), content: View::with(CalculatorView::new()),
key_monitor: RwLock::new(None) key_monitor: RwLock::new(None)
}).run(); })
.run();
} }

View file

@ -5,10 +5,10 @@ use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::view::View; use cacao::view::View;
use cacao::macos::{App, AppDelegate}; use cacao::image::{DrawConfig, Image, ImageView};
use cacao::macos::menu::{Menu, MenuItem}; use cacao::macos::menu::{Menu, MenuItem};
use cacao::macos::window::{Window}; use cacao::macos::window::Window;
use cacao::image::{ImageView, Image, DrawConfig}; use cacao::macos::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: Window, window: Window,
@ -22,7 +22,7 @@ impl Default for BasicApp {
let config = DrawConfig { let config = DrawConfig {
source: (100., 100.), source: (100., 100.),
target: (800., 800.), target: (800., 800.),
resize: cacao::image::ResizeBehavior::Stretch, resize: cacao::image::ResizeBehavior::Stretch
}; };
Self { Self {
@ -97,17 +97,15 @@ impl Default for BasicApp {
impl AppDelegate for BasicApp { impl AppDelegate for BasicApp {
fn did_finish_launching(&self) { fn did_finish_launching(&self) {
App::set_menu(vec![ App::set_menu(vec![Menu::new("", vec![
Menu::new("", vec![
MenuItem::Services, MenuItem::Services,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Hide, MenuItem::Hide,
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]) ])]);
]);
App::activate(); App::activate();
self.window.set_title("Hello World!"); self.window.set_title("Hello World!");
@ -120,7 +118,7 @@ impl AppDelegate for BasicApp {
self.image_view.top.constraint_equal_to(&self.content_view.top), self.image_view.top.constraint_equal_to(&self.content_view.top),
self.image_view.leading.constraint_equal_to(&self.content_view.leading), self.image_view.leading.constraint_equal_to(&self.content_view.leading),
self.image_view.trailing.constraint_equal_to(&self.content_view.trailing), self.image_view.trailing.constraint_equal_to(&self.content_view.trailing),
self.image_view.bottom.constraint_equal_to(&self.content_view.bottom), self.image_view.bottom.constraint_equal_to(&self.content_view.bottom)
]); ]);
self.window.set_content_view(&self.content_view); self.window.set_content_view(&self.content_view);

View file

@ -6,9 +6,9 @@ use cacao::geometry::Rect;
use cacao::layout::Layout; use cacao::layout::Layout;
use cacao::view::View; use cacao::view::View;
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
use cacao::appkit::{App, AppDelegate};
const CORNER_RADIUS: f64 = 16.; const CORNER_RADIUS: f64 = 16.;
const SPACING: f64 = 10.; const SPACING: f64 = 10.;
@ -30,23 +30,16 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![ Menu::new("View", vec![MenuItem::EnterFullScreen]),
MenuItem::CloseWindow
]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
]); ]);
App::activate(); App::activate();
@ -115,5 +108,6 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with(WindowConfig::default(), AppWindow::default()) window: Window::with(WindowConfig::default(), AppWindow::default())
}).run(); })
.run();
} }

View file

@ -1,9 +1,6 @@
use std::sync::RwLock; use std::sync::RwLock;
use cacao::uikit::{ use cacao::uikit::{App, AppDelegate, Scene, SceneConfig, SceneConnectionOptions, SceneSession, Window, WindowSceneDelegate};
App, AppDelegate, Scene, SceneConfig, SceneSession,
SceneConnectionOptions, WindowSceneDelegate, Window
};
use cacao::color::Color; use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
@ -44,12 +41,10 @@ impl ViewDelegate for RootView {
self.red.leading.constraint_equal_to(&view.leading).offset(16.), self.red.leading.constraint_equal_to(&view.leading).offset(16.),
self.red.trailing.constraint_equal_to(&view.trailing).offset(-16.), self.red.trailing.constraint_equal_to(&view.trailing).offset(-16.),
self.red.height.constraint_equal_to_constant(100.), self.red.height.constraint_equal_to_constant(100.),
self.green.top.constraint_equal_to(&self.red.bottom).offset(16.), self.green.top.constraint_equal_to(&self.red.bottom).offset(16.),
self.green.leading.constraint_equal_to(&view.leading).offset(16.), self.green.leading.constraint_equal_to(&view.leading).offset(16.),
self.green.trailing.constraint_equal_to(&view.trailing).offset(-16.), self.green.trailing.constraint_equal_to(&view.trailing).offset(-16.),
self.green.height.constraint_equal_to_constant(120.), self.green.height.constraint_equal_to_constant(120.),
self.blue.top.constraint_equal_to(&self.green.bottom).offset(16.), self.blue.top.constraint_equal_to(&self.green.bottom).offset(16.),
self.blue.leading.constraint_equal_to(&view.leading).offset(16.), self.blue.leading.constraint_equal_to(&view.leading).offset(16.),
self.blue.trailing.constraint_equal_to(&view.trailing).offset(-16.), self.blue.trailing.constraint_equal_to(&view.trailing).offset(-16.),
@ -65,12 +60,7 @@ pub struct WindowScene {
} }
impl WindowSceneDelegate for WindowScene { impl WindowSceneDelegate for WindowScene {
fn will_connect( fn will_connect(&self, scene: Scene, session: SceneSession, options: SceneConnectionOptions) {
&self,
scene: Scene,
session: SceneSession,
options: SceneConnectionOptions
) {
let bounds = scene.get_bounds(); let bounds = scene.get_bounds();
let mut window = Window::new(bounds); let mut window = Window::new(bounds);
window.set_window_scene(scene); window.set_window_scene(scene);
@ -90,7 +80,5 @@ impl WindowSceneDelegate for WindowScene {
} }
fn main() { fn main() {
App::new(TestApp::default(), || { App::new(TestApp::default(), || Box::new(WindowScene::default())).run();
Box::new(WindowScene::default())
}).run();
} }

View file

@ -1,13 +1,13 @@
//! This example showcases setting up a basic application and window, setting up some views to //! This example showcases setting up a basic application and window, setting up some views to
//! work with autolayout, and some basic ways to handle colors. //! work with autolayout, and some basic ways to handle colors.
use cacao::layout::{Layout, LayoutConstraint};
use cacao::input::{TextField, TextFieldDelegate}; use cacao::input::{TextField, TextFieldDelegate};
use cacao::layout::{Layout, LayoutConstraint};
use cacao::view::View; use cacao::view::View;
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
use cacao::appkit::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: Window<AppWindow> window: Window<AppWindow>
@ -23,13 +23,9 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![
MenuItem::CloseWindow
]),
Menu::new("Edit", vec![ Menu::new("Edit", vec![
MenuItem::Undo, MenuItem::Undo,
MenuItem::Redo, MenuItem::Redo,
@ -38,21 +34,16 @@ impl AppDelegate for BasicApp {
MenuItem::Copy, MenuItem::Copy,
MenuItem::Paste, MenuItem::Paste,
MenuItem::Separator, MenuItem::Separator,
MenuItem::SelectAll MenuItem::SelectAll,
]), ]),
Menu::new("View", vec![MenuItem::EnterFullScreen]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]), ]),
Menu::new("Help", vec![]),
Menu::new("Help", vec![])
]); ]);
App::activate(); App::activate();
@ -79,7 +70,6 @@ impl TextFieldDelegate for ConsoleLogger {
println!("Did change to: {}", value); println!("Did change to: {}", value);
} }
fn text_did_end_editing(&self, value: &str) { fn text_did_end_editing(&self, value: &str) {
println!("Ended: {}", value); println!("Ended: {}", value);
} }
@ -95,7 +85,7 @@ impl AppWindow {
pub fn new() -> Self { pub fn new() -> Self {
AppWindow { AppWindow {
input: TextField::with(ConsoleLogger), input: TextField::with(ConsoleLogger),
content: View::new(), content: View::new()
} }
} }
} }
@ -121,5 +111,6 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with(WindowConfig::default(), AppWindow::new()) window: Window::with(WindowConfig::default(), AppWindow::new())
}).run(); })
.run();
} }

View file

@ -9,16 +9,14 @@ mod view;
use view::AddNewTodoContentView; use view::AddNewTodoContentView;
pub struct AddNewTodoWindow { pub struct AddNewTodoWindow {
pub content: ViewController<AddNewTodoContentView>, pub content: ViewController<AddNewTodoContentView>
} }
impl AddNewTodoWindow { impl AddNewTodoWindow {
pub fn new() -> Self { pub fn new() -> Self {
let content = ViewController::new(AddNewTodoContentView::default()); let content = ViewController::new(AddNewTodoContentView::default());
AddNewTodoWindow { AddNewTodoWindow { content: content }
content: content
}
} }
pub fn on_message(&self, message: Message) { pub fn on_message(&self, message: Message) {

View file

@ -6,8 +6,8 @@
//! changes before version 0.1. This approach is unlikely to break as an example while those //! changes before version 0.1. This approach is unlikely to break as an example while those
//! changes are poked and prodded at, even if it is a bit verbose and confusing. //! changes are poked and prodded at, even if it is a bit verbose and confusing.
use cacao::text::Label;
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::text::Label;
use cacao::view::{View, ViewDelegate}; use cacao::view::{View, ViewDelegate};
use cacao::button::Button; use cacao::button::Button;
@ -60,11 +60,9 @@ impl ViewDelegate for AddNewTodoContentView {
instructions.top.constraint_equal_to(&view.top).offset(16.), instructions.top.constraint_equal_to(&view.top).offset(16.),
instructions.leading.constraint_equal_to(&view.leading).offset(16.), instructions.leading.constraint_equal_to(&view.leading).offset(16.),
instructions.trailing.constraint_equal_to(&view.trailing).offset(-16.), instructions.trailing.constraint_equal_to(&view.trailing).offset(-16.),
input.top.constraint_equal_to(&instructions.bottom).offset(8.), input.top.constraint_equal_to(&instructions.bottom).offset(8.),
input.leading.constraint_equal_to(&view.leading).offset(16.), input.leading.constraint_equal_to(&view.leading).offset(16.),
input.trailing.constraint_equal_to(&view.trailing).offset(-16.), input.trailing.constraint_equal_to(&view.trailing).offset(-16.),
button.top.constraint_equal_to(&input.bottom).offset(8.), button.top.constraint_equal_to(&input.bottom).offset(8.),
button.trailing.constraint_equal_to(&view.trailing).offset(-16.), button.trailing.constraint_equal_to(&view.trailing).offset(-16.),
button.bottom.constraint_equal_to(&view.bottom).offset(-16.) button.bottom.constraint_equal_to(&view.bottom).offset(-16.)

View file

@ -14,8 +14,5 @@ mod todos;
mod windows; mod windows;
fn main() { fn main() {
App::new( App::new("com.cacao.todo", app::TodosApp::default()).run();
"com.cacao.todo",
app::TodosApp::default()
).run();
} }

View file

@ -14,11 +14,9 @@ pub fn menu() -> Vec<Menu> {
Menu::new("", vec![ Menu::new("", vec![
MenuItem::About("Todos".to_string()), MenuItem::About("Todos".to_string()),
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Preferences").key(",").action(|| { MenuItem::new("Preferences").key(",").action(|| {
dispatch_ui(Message::OpenPreferencesWindow); dispatch_ui(Message::OpenPreferencesWindow);
}), }),
MenuItem::Separator, MenuItem::Separator,
MenuItem::Services, MenuItem::Services,
MenuItem::Separator, MenuItem::Separator,
@ -26,24 +24,19 @@ pub fn menu() -> Vec<Menu> {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![ Menu::new("File", vec![
MenuItem::new("Open/Show Window").key("n").action(|| { MenuItem::new("Open/Show Window").key("n").action(|| {
dispatch_ui(Message::OpenMainWindow); dispatch_ui(Message::OpenMainWindow);
}), }),
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Add Todo").key("+").action(|| { MenuItem::new("Add Todo").key("+").action(|| {
dispatch_ui(Message::OpenNewTodoSheet); dispatch_ui(Message::OpenNewTodoSheet);
}), }),
MenuItem::Separator, MenuItem::Separator,
MenuItem::CloseWindow MenuItem::CloseWindow,
]), ]),
Menu::new("Edit", vec![ Menu::new("Edit", vec![
MenuItem::Undo, MenuItem::Undo,
MenuItem::Redo, MenuItem::Redo,
@ -52,20 +45,15 @@ pub fn menu() -> Vec<Menu> {
MenuItem::Copy, MenuItem::Copy,
MenuItem::Paste, MenuItem::Paste,
MenuItem::Separator, MenuItem::Separator,
MenuItem::SelectAll MenuItem::SelectAll,
]), ]),
Menu::new("View", vec![MenuItem::EnterFullScreen]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]), ]),
Menu::new("Help", vec![]),
Menu::new("Help", vec![])
] ]
} }

View file

@ -1,5 +1,5 @@
use cacao::text::{Label, TextAlign};
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::text::{Label, TextAlign};
use cacao::view::{View, ViewDelegate}; use cacao::view::{View, ViewDelegate};
/// A blank advanced preferences view. /// A blank advanced preferences view.
@ -12,7 +12,8 @@ impl ViewDelegate for AdvancedPreferencesContentView {
const NAME: &'static str = "AdvancedPreferencesContentView"; const NAME: &'static str = "AdvancedPreferencesContentView";
fn did_load(&mut self, view: View) { fn did_load(&mut self, view: View) {
self.label.set_text("And this is where advanced preferences would be... if we had any."); self.label
.set_text("And this is where advanced preferences would be... if we had any.");
self.label.set_text_alignment(TextAlign::Center); self.label.set_text_alignment(TextAlign::Center);
view.add_subview(&self.label); view.add_subview(&self.label);
@ -24,4 +25,3 @@ impl ViewDelegate for AdvancedPreferencesContentView {
]); ]);
} }
} }

View file

@ -12,7 +12,7 @@ use super::toggle_option_view::ToggleOptionView;
/// A general preferences view. /// A general preferences view.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct GeneralPreferencesContentView { pub struct GeneralPreferencesContentView {
pub example_option: ToggleOptionView, pub example_option: ToggleOptionView
} }
impl ViewDelegate for GeneralPreferencesContentView { impl ViewDelegate for GeneralPreferencesContentView {
@ -30,10 +30,17 @@ impl ViewDelegate for GeneralPreferencesContentView {
LayoutConstraint::activate(&[ LayoutConstraint::activate(&[
self.example_option.view.top.constraint_equal_to(&view.top).offset(22.), self.example_option.view.top.constraint_equal_to(&view.top).offset(22.),
self.example_option.view.leading.constraint_equal_to(&view.leading).offset(22.), self.example_option
self.example_option.view.trailing.constraint_equal_to(&view.trailing).offset(-22.), .view
.leading
.constraint_equal_to(&view.leading)
.offset(22.),
self.example_option
.view
.trailing
.constraint_equal_to(&view.trailing)
.offset(-22.),
self.example_option.view.bottom.constraint_equal_to(&view.bottom).offset(-22.) self.example_option.view.bottom.constraint_equal_to(&view.bottom).offset(-22.)
]); ]);
} }
} }

View file

@ -1,7 +1,7 @@
//! Implements a stock-ish Preferences window. //! Implements a stock-ish Preferences window.
use cacao::appkit::window::{Window, WindowDelegate};
use cacao::appkit::toolbar::Toolbar; use cacao::appkit::toolbar::Toolbar;
use cacao::appkit::window::{Window, WindowDelegate};
use cacao::view::ViewController; use cacao::view::ViewController;
use crate::storage::Message; use crate::storage::Message;

View file

@ -1,7 +1,7 @@
use cacao::text::Label;
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::switch::Switch; use cacao::switch::Switch;
use cacao::view::{View}; use cacao::text::Label;
use cacao::view::View;
/// A reusable widget for a toggle; this is effectively a standard checkbox/label combination for /// A reusable widget for a toggle; this is effectively a standard checkbox/label combination for
/// toggling a boolean value. /// toggling a boolean value.
@ -31,11 +31,9 @@ impl Default for ToggleOptionView {
switch.top.constraint_equal_to(&view.top), switch.top.constraint_equal_to(&view.top),
switch.leading.constraint_equal_to(&view.leading), switch.leading.constraint_equal_to(&view.leading),
switch.width.constraint_equal_to_constant(24.), switch.width.constraint_equal_to_constant(24.),
title.top.constraint_equal_to(&view.top), title.top.constraint_equal_to(&view.top),
title.leading.constraint_equal_to(&switch.trailing), title.leading.constraint_equal_to(&switch.trailing),
title.trailing.constraint_equal_to(&view.trailing), title.trailing.constraint_equal_to(&view.trailing),
subtitle.top.constraint_equal_to(&title.bottom), subtitle.top.constraint_equal_to(&title.bottom),
subtitle.leading.constraint_equal_to(&switch.trailing), subtitle.leading.constraint_equal_to(&switch.trailing),
subtitle.trailing.constraint_equal_to(&view.trailing), subtitle.trailing.constraint_equal_to(&view.trailing),

View file

@ -1,7 +1,7 @@
//! Implements an example toolbar for a Preferences app. Could be cleaner, probably worth cleaning //! Implements an example toolbar for a Preferences app. Could be cleaner, probably worth cleaning
//! up at some point. //! up at some point.
use cacao::appkit::toolbar::{Toolbar, ToolbarDelegate, ToolbarItem, ItemIdentifier}; use cacao::appkit::toolbar::{ItemIdentifier, Toolbar, ToolbarDelegate, ToolbarItem};
use cacao::image::{Image, MacSystemIcon}; use cacao::image::{Image, MacSystemIcon};
use crate::storage::{dispatch_ui, Message}; use crate::storage::{dispatch_ui, Message};
@ -11,7 +11,8 @@ pub struct PreferencesToolbar((ToolbarItem, ToolbarItem));
impl Default for PreferencesToolbar { impl Default for PreferencesToolbar {
fn default() -> Self { fn default() -> Self {
PreferencesToolbar(({ PreferencesToolbar((
{
let mut item = ToolbarItem::new("general"); let mut item = ToolbarItem::new("general");
item.set_title("General"); item.set_title("General");
@ -23,7 +24,8 @@ impl Default for PreferencesToolbar {
}); });
item item
}, { },
{
let mut item = ToolbarItem::new("advanced"); let mut item = ToolbarItem::new("advanced");
item.set_title("Advanced"); item.set_title("Advanced");
@ -35,7 +37,8 @@ impl Default for PreferencesToolbar {
}); });
item item
})) }
))
} }
} }
@ -60,9 +63,11 @@ impl ToolbarDelegate for PreferencesToolbar {
fn item_for(&self, identifier: &str) -> &ToolbarItem { fn item_for(&self, identifier: &str) -> &ToolbarItem {
match identifier { match identifier {
"general" => &self.0.0, "general" => &self.0 .0,
"advanced" => &self.0.1, "advanced" => &self.0 .1,
_ => { unreachable!(); } _ => {
unreachable!();
}
} }
} }
} }

View file

@ -52,7 +52,10 @@ fn toggle_bool(key: &str) {
panic!("Attempting to toggle a boolean value for {}, but it's not a boolean.", key); panic!("Attempting to toggle a boolean value for {}, but it's not a boolean.", key);
} }
panic!("Attempting to toggle a boolean value for {}, but this key does not exist.", key); panic!(
"Attempting to toggle a boolean value for {}, but this key does not exist.",
key
);
} }
/// A helper method for loading a boolean value held at the specified key. If the value cannot /// A helper method for loading a boolean value held at the specified key. If the value cannot

View file

@ -9,7 +9,7 @@ mod defaults;
pub use defaults::Defaults; pub use defaults::Defaults;
mod todos; mod todos;
pub use todos::{Todos, Todo, TodoStatus}; pub use todos::{Todo, TodoStatus, Todos};
/// Message passing is our primary way of instructing UI changes without needing to do /// Message passing is our primary way of instructing UI changes without needing to do
/// constant crazy referencing in Rust. Dispatch a method using either `dispatch_ui` for the main /// constant crazy referencing in Rust. Dispatch a method using either `dispatch_ui` for the main

View file

@ -2,8 +2,8 @@
//! doing this stuff on the main thread; in a more complicated app, you'd probably make different //! doing this stuff on the main thread; in a more complicated app, you'd probably make different
//! choices. //! choices.
use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
/// The status of a Todo. /// The status of a Todo.
#[derive(Debug)] #[derive(Debug)]

View file

@ -7,8 +7,8 @@ use cacao::layout::{Layout, LayoutConstraint};
use cacao::listview::ListView; use cacao::listview::ListView;
use cacao::view::{View, ViewDelegate}; use cacao::view::{View, ViewDelegate};
use crate::storage::Message;
use super::list::TodosListView; use super::list::TodosListView;
use crate::storage::Message;
#[derive(Debug)] #[derive(Debug)]
pub struct TodosContentView { pub struct TodosContentView {

View file

@ -2,12 +2,9 @@
//! mostly single-threaded example, so we can get away with cutting a few corners and keeping our //! mostly single-threaded example, so we can get away with cutting a few corners and keeping our
//! data store in here - but for a larger app, you'd likely do something else. //! data store in here - but for a larger app, you'd likely do something else.
use cacao::listview::{ use cacao::listview::{ListView, ListViewDelegate, ListViewRow, RowAction, RowActionStyle, RowAnimation, RowEdge};
ListView, ListViewDelegate, ListViewRow,
RowAnimation, RowEdge, RowAction, RowActionStyle
};
use crate::storage::{dispatch_ui, Message, Todos, TodoStatus}; use crate::storage::{dispatch_ui, Message, TodoStatus, Todos};
mod row; mod row;
use row::TodoViewRow; use row::TodoViewRow;
@ -97,15 +94,23 @@ impl ListViewDelegate for TodosListView {
self.todos.with(row, |todo| match todo.status { self.todos.with(row, |todo| match todo.status {
TodoStatus::Complete => { TodoStatus::Complete => {
actions.push(RowAction::new("Mark Incomplete", RowActionStyle::Destructive, move |_action, row| { actions.push(RowAction::new(
"Mark Incomplete",
RowActionStyle::Destructive,
move |_action, row| {
dispatch_ui(Message::MarkTodoIncomplete(row)); dispatch_ui(Message::MarkTodoIncomplete(row));
})); }
));
}, },
TodoStatus::Incomplete => { TodoStatus::Incomplete => {
actions.push(RowAction::new("Mark Complete", RowActionStyle::Regular, move |_action, row| { actions.push(RowAction::new(
"Mark Complete",
RowActionStyle::Regular,
move |_action, row| {
dispatch_ui(Message::MarkTodoComplete(row)); dispatch_ui(Message::MarkTodoComplete(row));
})); }
));
} }
}); });

View file

@ -1,7 +1,7 @@
use cacao::color::Color;
use cacao::layout::{Layout, LayoutConstraint}; use cacao::layout::{Layout, LayoutConstraint};
use cacao::text::{Font, Label, LineBreakMode}; use cacao::text::{Font, Label, LineBreakMode};
use cacao::view::{View, ViewDelegate}; use cacao::view::{View, ViewDelegate};
use cacao::color::Color;
use crate::storage::{Todo, TodoStatus}; use crate::storage::{Todo, TodoStatus};
@ -50,7 +50,6 @@ impl ViewDelegate for TodoViewRow {
self.title.top.constraint_equal_to(&view.top).offset(16.), self.title.top.constraint_equal_to(&view.top).offset(16.),
self.title.leading.constraint_equal_to(&view.leading).offset(16.), self.title.leading.constraint_equal_to(&view.leading).offset(16.),
self.title.trailing.constraint_equal_to(&view.trailing).offset(-16.), self.title.trailing.constraint_equal_to(&view.trailing).offset(-16.),
self.status.top.constraint_equal_to(&self.title.bottom).offset(8.), self.status.top.constraint_equal_to(&self.title.bottom).offset(8.),
self.status.leading.constraint_equal_to(&view.leading).offset(16.), self.status.leading.constraint_equal_to(&view.leading).offset(16.),
self.status.trailing.constraint_equal_to(&view.trailing).offset(-16.), self.status.trailing.constraint_equal_to(&view.trailing).offset(-16.),

View file

@ -1,7 +1,7 @@
//! The main Todos window. //! The main Todos window.
use cacao::appkit::window::{Window, WindowDelegate};
use cacao::appkit::toolbar::Toolbar; use cacao::appkit::toolbar::Toolbar;
use cacao::appkit::window::{Window, WindowDelegate};
use cacao::view::ViewController; use cacao::view::ViewController;
use crate::storage::Message; use crate::storage::Message;
@ -16,7 +16,7 @@ mod list;
pub struct TodosWindow { pub struct TodosWindow {
pub content: ViewController<TodosContentView>, pub content: ViewController<TodosContentView>,
pub toolbar: Toolbar<TodosToolbar>, pub toolbar: Toolbar<TodosToolbar>
} }
impl TodosWindow { impl TodosWindow {

View file

@ -1,10 +1,7 @@
//! The main Todos window toolbar. Contains a button to enable adding a new task. //! The main Todos window toolbar. Contains a button to enable adding a new task.
use cacao::appkit::toolbar::{ItemIdentifier, Toolbar, ToolbarDelegate, ToolbarDisplayMode, ToolbarItem};
use cacao::button::Button; use cacao::button::Button;
use cacao::appkit::toolbar::{
Toolbar, ToolbarDelegate, ToolbarItem,
ToolbarDisplayMode, ItemIdentifier
};
use crate::storage::{dispatch_ui, Message}; use crate::storage::{dispatch_ui, Message};

View file

@ -5,14 +5,14 @@
use std::sync::RwLock; use std::sync::RwLock;
use cacao::appkit::window::{Window, WindowConfig, WindowStyle, WindowDelegate, WindowToolbarStyle}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate, WindowStyle, WindowToolbarStyle};
use cacao::notification_center::Dispatcher; use cacao::notification_center::Dispatcher;
use crate::storage::Message; use crate::storage::Message;
use crate::add::AddNewTodoWindow; use crate::add::AddNewTodoWindow;
use crate::todos::TodosWindow;
use crate::preferences::PreferencesWindow; use crate::preferences::PreferencesWindow;
use crate::todos::TodosWindow;
#[derive(Default)] #[derive(Default)]
pub struct WindowManager { pub struct WindowManager {
@ -42,9 +42,7 @@ where
impl WindowManager { impl WindowManager {
pub fn open_main(&self) { pub fn open_main(&self) {
open_or_show(&self.main, || ( open_or_show(&self.main, || (WindowConfig::default(), TodosWindow::new()));
WindowConfig::default(), TodosWindow::new()
));
} }
/// When we run a sheet, we want to run it on our main window, which is all /// When we run a sheet, we want to run it on our main window, which is all
@ -100,8 +98,10 @@ impl WindowManager {
config.set_initial_dimensions(100., 100., 400., 400.); config.set_initial_dimensions(100., 100., 400., 400.);
config.set_styles(&[ config.set_styles(&[
WindowStyle::Resizable, WindowStyle::Miniaturizable, WindowStyle::Resizable,
WindowStyle::Closable, WindowStyle::Titled WindowStyle::Miniaturizable,
WindowStyle::Closable,
WindowStyle::Titled
]); ]);
config.toolbar_style = WindowToolbarStyle::Preferences; config.toolbar_style = WindowToolbarStyle::Preferences;

View file

@ -3,10 +3,10 @@
use cacao::webview::{WebView, WebViewConfig, WebViewDelegate}; use cacao::webview::{WebView, WebViewConfig, WebViewDelegate};
use cacao::macos::{App, AppDelegate};
use cacao::macos::menu::{Menu, MenuItem}; use cacao::macos::menu::{Menu, MenuItem};
use cacao::macos::toolbar::Toolbar; use cacao::macos::toolbar::Toolbar;
use cacao::macos::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle}; use cacao::macos::window::{Window, WindowConfig, WindowDelegate, WindowToolbarStyle};
use cacao::macos::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: Window<AppWindow> window: Window<AppWindow>
@ -56,8 +56,8 @@ impl WebViewDelegate for WebViewInstance {
return match requested_asset_path.as_str() { return match requested_asset_path.as_str() {
"/hello.html" => Some(link_html.as_bytes().into()), "/hello.html" => Some(link_html.as_bytes().into()),
_ => Some(index_html.as_bytes().into()), _ => Some(index_html.as_bytes().into())
} };
} }
} }
@ -100,5 +100,6 @@ impl WindowDelegate for AppWindow {
fn main() { fn main() {
App::new("com.test.window", BasicApp { App::new("com.test.window", BasicApp {
window: Window::with(WindowConfig::default(), AppWindow::new()) window: Window::with(WindowConfig::default(), AppWindow::new())
}).run(); })
.run();
} }

View file

@ -1,8 +1,8 @@
//! This example showcases setting up a basic application and window. //! This example showcases setting up a basic application and window.
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::Window; use cacao::appkit::window::Window;
use cacao::appkit::{App, AppDelegate};
#[derive(Default)] #[derive(Default)]
struct BasicApp { struct BasicApp {
@ -19,23 +19,16 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![ Menu::new("View", vec![MenuItem::EnterFullScreen]),
MenuItem::CloseWindow
]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
]); ]);
App::activate(); App::activate();

View file

@ -4,9 +4,9 @@
//! //!
//! If you're not using that, you can probably get by fine with a standard `NSWindow`. //! If you're not using that, you can probably get by fine with a standard `NSWindow`.
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowDelegate};
use cacao::appkit::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: WindowController<MyWindow> window: WindowController<MyWindow>
@ -22,23 +22,16 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![ Menu::new("View", vec![MenuItem::EnterFullScreen]),
MenuItem::CloseWindow
]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
]); ]);
App::activate(); App::activate();
@ -70,5 +63,6 @@ impl WindowDelegate for MyWindow {
fn main() { fn main() {
App::new("com.test.window-delegate", BasicApp { App::new("com.test.window-delegate", BasicApp {
window: WindowController::with(WindowConfig::default(), MyWindow::default()) window: WindowController::with(WindowConfig::default(), MyWindow::default())
}).run(); })
.run();
} }

View file

@ -1,9 +1,9 @@
//! This example showcases setting up a basic application and window delegate. //! This example showcases setting up a basic application and window delegate.
//! Window Delegate's give you lifecycle methods that you can respond to. //! Window Delegate's give you lifecycle methods that you can respond to.
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::menu::{Menu, MenuItem}; use cacao::appkit::menu::{Menu, MenuItem};
use cacao::appkit::window::{Window, WindowConfig, WindowDelegate}; use cacao::appkit::window::{Window, WindowConfig, WindowDelegate};
use cacao::appkit::{App, AppDelegate};
struct BasicApp { struct BasicApp {
window: Window<MyWindow> window: Window<MyWindow>
@ -19,23 +19,16 @@ impl AppDelegate for BasicApp {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![ Menu::new("View", vec![MenuItem::EnterFullScreen]),
MenuItem::CloseWindow
]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
]); ]);
App::activate(); App::activate();
@ -80,5 +73,6 @@ impl WindowDelegate for MyWindow {
fn main() { fn main() {
App::new("com.test.window-delegate", BasicApp { App::new("com.test.window-delegate", BasicApp {
window: Window::with(WindowConfig::default(), MyWindow::default()) window: Window::with(WindowConfig::default(), MyWindow::default())
}).run(); })
.run();
} }

6
rustfmt.toml Normal file
View file

@ -0,0 +1,6 @@
max_width = 130
match_block_trailing_comma = true
# Nightly
overflow_delimited_expr = true
trailing_comma = "Never"

View file

@ -24,9 +24,9 @@
//! } //! }
//! ``` //! ```
use objc_id::Id;
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, NSString}; use crate::foundation::{id, NSString};
@ -45,9 +45,9 @@ impl Alert {
Alert(unsafe { Alert(unsafe {
let alert: id = msg_send![class!(NSAlert), new]; let alert: id = msg_send![class!(NSAlert), new];
let _: () = msg_send![alert, setMessageText:title]; let _: () = msg_send![alert, setMessageText: title];
let _: () = msg_send![alert, setInformativeText:message]; let _: () = msg_send![alert, setInformativeText: message];
let _: () = msg_send![alert, addButtonWithTitle:ok]; let _: () = msg_send![alert, addButtonWithTitle: ok];
Id::from_ptr(alert) Id::from_ptr(alert)
}) })
} }

View file

@ -16,7 +16,7 @@ impl AnimationContext {
/// Sets the animation duration. /// Sets the animation duration.
pub fn set_duration(&mut self, duration: f64) { pub fn set_duration(&mut self, duration: f64) {
unsafe { unsafe {
let _: () = msg_send![self.0, setDuration:duration]; let _: () = msg_send![self.0, setDuration: duration];
} }
} }
@ -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];
} }
} }

View file

@ -6,7 +6,7 @@ use std::sync::Once;
use objc::class; use objc::class;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class}; use objc::runtime::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() -> *const Class {
@ -19,7 +19,5 @@ pub(crate) fn register_app_class() -> *const Class {
APP_CLASS = decl.register(); APP_CLASS = decl.register();
}); });
unsafe { unsafe { APP_CLASS }
APP_CLASS
}
} }

View file

@ -7,16 +7,16 @@ use std::sync::Once;
use block::Block; use block::Block;
use objc::{class, msg_send, sel, sel_impl};
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use url::Url; use url::Url;
use crate::error::Error; use crate::appkit::app::{AppDelegate, APP_PTR};
use crate::foundation::{id, nil, to_bool, BOOL, YES, NO, NSUInteger, NSArray, NSString};
use crate::appkit::app::{APP_PTR, AppDelegate};
use crate::appkit::printing::PrintSettings; use crate::appkit::printing::PrintSettings;
use crate::error::Error;
use crate::foundation::{id, nil, to_bool, NSArray, NSString, NSUInteger, BOOL, NO, YES};
use crate::user_activity::UserActivity; use crate::user_activity::UserActivity;
#[cfg(feature = "cloudkit")] #[cfg(feature = "cloudkit")]
@ -33,78 +33,78 @@ fn app<T>(this: &Object) -> &T {
} }
/// Fires when the Application Delegate receives a `applicationWillFinishLaunching` notification. /// Fires when the Application Delegate receives a `applicationWillFinishLaunching` notification.
extern fn will_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_finish_launching(); app::<T>(this).will_finish_launching();
} }
/// Fires when the Application Delegate receives a `applicationDidFinishLaunching` notification. /// Fires when the Application Delegate receives a `applicationDidFinishLaunching` notification.
extern fn did_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_finish_launching<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_finish_launching(); app::<T>(this).did_finish_launching();
} }
/// Fires when the Application Delegate receives a `applicationWillBecomeActive` notification. /// Fires when the Application Delegate receives a `applicationWillBecomeActive` notification.
extern fn will_become_active<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_become_active<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_become_active(); app::<T>(this).will_become_active();
} }
/// Fires when the Application Delegate receives a `applicationDidBecomeActive` notification. /// Fires when the Application Delegate receives a `applicationDidBecomeActive` notification.
extern fn did_become_active<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_become_active<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_become_active(); app::<T>(this).did_become_active();
} }
/// Fires when the Application Delegate receives a `applicationWillResignActive` notification. /// Fires when the Application Delegate receives a `applicationWillResignActive` notification.
extern fn will_resign_active<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_resign_active<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_resign_active(); app::<T>(this).will_resign_active();
} }
/// Fires when the Application Delegate receives a `applicationDidResignActive` notification. /// Fires when the Application Delegate receives a `applicationDidResignActive` notification.
extern fn did_resign_active<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_resign_active<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_resign_active(); app::<T>(this).did_resign_active();
} }
/// Fires when the Application Delegate receives a 'applicationShouldTerminate:` notification. /// Fires when the Application Delegate receives a 'applicationShouldTerminate:` notification.
extern fn should_terminate<T: AppDelegate>(this: &Object, _: Sel, _: id) -> NSUInteger { extern "C" fn should_terminate<T: AppDelegate>(this: &Object, _: Sel, _: id) -> NSUInteger {
app::<T>(this).should_terminate().into() app::<T>(this).should_terminate().into()
} }
/// Fires when the Application Delegate receives a `applicationWillTerminate:` notification. /// Fires when the Application Delegate receives a `applicationWillTerminate:` notification.
extern fn will_terminate<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_terminate<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_terminate(); app::<T>(this).will_terminate();
} }
/// Fires when the Application Delegate receives a `applicationWillHide:` notification. /// Fires when the Application Delegate receives a `applicationWillHide:` notification.
extern fn will_hide<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_hide<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_hide(); app::<T>(this).will_hide();
} }
/// Fires when the Application Delegate receives a `applicationDidHide:` notification. /// Fires when the Application Delegate receives a `applicationDidHide:` notification.
extern fn did_hide<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_hide<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_hide(); app::<T>(this).did_hide();
} }
/// Fires when the Application Delegate receives a `applicationWillUnhide:` notification. /// Fires when the Application Delegate receives a `applicationWillUnhide:` notification.
extern fn will_unhide<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_unhide<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_unhide(); app::<T>(this).will_unhide();
} }
/// Fires when the Application Delegate receives a `applicationDidUnhide:` notification. /// Fires when the Application Delegate receives a `applicationDidUnhide:` notification.
extern fn did_unhide<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_unhide<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_unhide(); app::<T>(this).did_unhide();
} }
/// Fires when the Application Delegate receives a `applicationWillUpdate:` notification. /// Fires when the Application Delegate receives a `applicationWillUpdate:` notification.
extern fn will_update<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_update<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).will_update(); app::<T>(this).will_update();
} }
/// Fires when the Application Delegate receives a `applicationDidUpdate:` notification. /// Fires when the Application Delegate receives a `applicationDidUpdate:` notification.
extern fn did_update<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_update<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_update(); app::<T>(this).did_update();
} }
/// Fires when the Application Delegate receives a /// Fires when the Application Delegate receives a
/// `applicationShouldHandleReopen:hasVisibleWindows:` notification. /// `applicationShouldHandleReopen:hasVisibleWindows:` notification.
extern 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)) { match app::<T>(this).should_handle_reopen(to_bool(has_visible_windows)) {
true => YES, true => YES,
false => NO false => NO
@ -113,7 +113,7 @@ extern fn should_handle_reopen<T: AppDelegate>(this: &Object, _: Sel, _: id, has
/// Fires when the application delegate receives a `applicationDockMenu:` request. /// Fires when the application delegate receives a `applicationDockMenu:` request.
// @TODO: Make this return Vec<MenuItem>. // @TODO: Make this return Vec<MenuItem>.
extern fn dock_menu<T: AppDelegate>(this: &Object, _: Sel, _: id) -> id { extern "C" fn dock_menu<T: AppDelegate>(this: &Object, _: Sel, _: id) -> id {
match app::<T>(this).dock_menu() { match app::<T>(this).dock_menu() {
Some(mut menu) => &mut *menu.0, Some(mut menu) => &mut *menu.0,
None => nil None => nil
@ -121,19 +121,19 @@ extern fn dock_menu<T: AppDelegate>(this: &Object, _: Sel, _: id) -> id {
} }
/// Fires when the application delegate receives a `application:willPresentError:` notification. /// Fires when the application delegate receives a `application:willPresentError:` notification.
extern fn will_present_error<T: AppDelegate>(this: &Object, _: Sel, _: id, error: id) -> id { extern "C" fn will_present_error<T: AppDelegate>(this: &Object, _: Sel, _: id, error: id) -> id {
let error = Error::new(error); let error = Error::new(error);
app::<T>(this).will_present_error(error).into_nserror() app::<T>(this).will_present_error(error).into_nserror()
} }
/// Fires when the application receives a `applicationDidChangeScreenParameters:` notification. /// Fires when the application receives a `applicationDidChangeScreenParameters:` notification.
extern fn did_change_screen_parameters<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_screen_parameters<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).did_change_screen_parameters(); app::<T>(this).did_change_screen_parameters();
} }
/// Fires when the application receives a `application:willContinueUserActivityWithType:` /// Fires when the application receives a `application:willContinueUserActivityWithType:`
/// notification. /// notification.
extern 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()) { match app::<T>(this).will_continue_user_activity(activity.to_str()) {
@ -143,7 +143,7 @@ extern fn will_continue_user_activity_with_type<T: AppDelegate>(this: &Object, _
} }
/// Fires when the application receives a `application:continueUserActivity:restorationHandler:` notification. /// Fires when the application receives a `application:continueUserActivity:restorationHandler:` notification.
extern 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.
@ -160,57 +160,52 @@ extern fn continue_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, a
/// Fires when the application receives a /// Fires when the application receives a
/// `application:didFailToContinueUserActivityWithType:error:` message. /// `application:didFailToContinueUserActivityWithType:error:` message.
extern fn failed_to_continue_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity_type: id, error: id) { extern "C" fn failed_to_continue_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity_type: id, error: id) {
app::<T>(this).failed_to_continue_user_activity( app::<T>(this).failed_to_continue_user_activity(NSString::retain(activity_type).to_str(), Error::new(error));
NSString::retain(activity_type).to_str(),
Error::new(error)
);
} }
/// Fires when the application receives a `application:didUpdateUserActivity:` message. /// Fires when the application receives a `application:didUpdateUserActivity:` message.
extern fn did_update_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity: id) { extern "C" fn did_update_user_activity<T: AppDelegate>(this: &Object, _: Sel, _: id, activity: id) {
let activity = UserActivity::with_inner(activity); let activity = UserActivity::with_inner(activity);
app::<T>(this).updated_user_activity(activity); app::<T>(this).updated_user_activity(activity);
} }
/// Fires when the application receives a `application:didRegisterForRemoteNotificationsWithDeviceToken:` message. /// Fires when the application receives a `application:didRegisterForRemoteNotificationsWithDeviceToken:` message.
extern fn registered_for_remote_notifications<T: AppDelegate>(_this: &Object, _: Sel, _: id, _: id) { extern "C" fn registered_for_remote_notifications<T: AppDelegate>(_this: &Object, _: Sel, _: id, _: id) {}
}
/// Fires when the application receives a `application:didFailToRegisterForRemoteNotificationsWithError:` message. /// Fires when the application receives a `application:didFailToRegisterForRemoteNotificationsWithError:` message.
extern fn failed_to_register_for_remote_notifications<T: AppDelegate>(this: &Object, _: Sel, _: id, error: id) { extern "C" fn failed_to_register_for_remote_notifications<T: AppDelegate>(this: &Object, _: Sel, _: id, error: id) {
app::<T>(this).failed_to_register_for_remote_notifications(Error::new(error)); app::<T>(this).failed_to_register_for_remote_notifications(Error::new(error));
} }
/// Fires when the application receives a `application:didReceiveRemoteNotification:` message. /// Fires when the application receives a `application:didReceiveRemoteNotification:` message.
extern fn did_receive_remote_notification<T: AppDelegate>(_this: &Object, _: Sel, _: id, _: id) { extern "C" fn did_receive_remote_notification<T: AppDelegate>(_this: &Object, _: Sel, _: id, _: id) {}
}
/// Fires when the application receives a `application:userDidAcceptCloudKitShareWithMetadata:` /// Fires when the application receives a `application:userDidAcceptCloudKitShareWithMetadata:`
/// message. /// message.
#[cfg(feature = "cloudkit")] #[cfg(feature = "cloudkit")]
extern fn accepted_cloudkit_share<T: AppDelegate>(this: &Object, _: Sel, _: id, metadata: id) { extern "C" fn accepted_cloudkit_share<T: AppDelegate>(this: &Object, _: Sel, _: id, metadata: id) {
let share = CKShareMetaData::with_inner(metadata); let share = CKShareMetaData::with_inner(metadata);
app::<T>(this).user_accepted_cloudkit_share(share); app::<T>(this).user_accepted_cloudkit_share(share);
} }
/// Fires when the application receives an `application:openURLs` message. /// Fires when the application receives an `application:openURLs` message.
extern fn open_urls<T: AppDelegate>(this: &Object, _: Sel, _: id, file_urls: id) { extern "C" fn open_urls<T: AppDelegate>(this: &Object, _: Sel, _: id, file_urls: id) {
let urls = NSArray::retain(file_urls).map(|url| { let urls = NSArray::retain(file_urls)
let uri = NSString::retain(unsafe { .map(|url| {
msg_send![url, absoluteString] let uri = NSString::retain(unsafe { msg_send![url, absoluteString] });
});
Url::parse(uri.to_str()) Url::parse(uri.to_str())
}).into_iter().filter_map(|url| url.ok()).collect(); })
.into_iter()
.filter_map(|url| url.ok())
.collect();
app::<T>(this).open_urls(urls); app::<T>(this).open_urls(urls);
} }
/// Fires when the application receives an `application:openFileWithoutUI:` message. /// Fires when the application receives an `application:openFileWithoutUI:` message.
extern 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()) { match app::<T>(this).open_file_without_ui(filename.to_str()) {
@ -220,7 +215,7 @@ extern fn open_file_without_ui<T: AppDelegate>(this: &Object, _: Sel, _: id, fil
} }
/// Fired when the application receives an `applicationShouldOpenUntitledFile:` message. /// Fired when the application receives an `applicationShouldOpenUntitledFile:` message.
extern 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() { match app::<T>(this).should_open_untitled_file() {
true => YES, true => YES,
false => NO false => NO
@ -228,7 +223,7 @@ extern fn should_open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id
} }
/// Fired when the application receives an `applicationShouldTerminateAfterLastWindowClosed:` message. /// Fired when the application receives an `applicationShouldTerminateAfterLastWindowClosed:` message.
extern 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() { match app::<T>(this).should_terminate_after_last_window_closed() {
true => YES, true => YES,
false => NO false => NO
@ -236,7 +231,7 @@ extern fn should_terminate_after_last_window_closed<T: AppDelegate>(this: &Objec
} }
/// Fired when the application receives an `applicationOpenUntitledFile:` message. /// Fired when the application receives an `applicationOpenUntitledFile:` message.
extern 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() { match app::<T>(this).open_untitled_file() {
true => YES, true => YES,
false => NO false => NO
@ -244,7 +239,7 @@ extern fn open_untitled_file<T: AppDelegate>(this: &Object, _: Sel, _: id) -> BO
} }
/// Fired when the application receives an `application:openTempFile:` message. /// Fired when the application receives an `application:openTempFile:` message.
extern 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()) { match app::<T>(this).open_temp_file(filename.to_str()) {
@ -254,7 +249,7 @@ extern fn open_temp_file<T: AppDelegate>(this: &Object, _: Sel, _: id, filename:
} }
/// Fired when the application receives an `application:printFile:` message. /// Fired when the application receives an `application:printFile:` message.
extern 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()) { match app::<T>(this).print_file(filename.to_str()) {
@ -265,10 +260,15 @@ extern fn print_file<T: AppDelegate>(this: &Object, _: Sel, _: id, file: id) ->
/// Fired when the application receives an `application:printFiles:withSettings:showPrintPanels:` /// Fired when the application receives an `application:printFiles:withSettings:showPrintPanels:`
/// message. /// message.
extern fn print_files<T: AppDelegate>(this: &Object, _: Sel, _: id, files: id, settings: id, show_print_panels: BOOL) -> NSUInteger { extern "C" fn print_files<T: AppDelegate>(
let files = NSArray::retain(files).map(|file| { this: &Object,
NSString::retain(file).to_str().to_string() _: Sel,
}); _: id,
files: id,
settings: id,
show_print_panels: BOOL
) -> NSUInteger {
let files = NSArray::retain(files).map(|file| NSString::retain(file).to_str().to_string());
let settings = PrintSettings::with_inner(settings); let settings = PrintSettings::with_inner(settings);
@ -276,14 +276,14 @@ extern fn print_files<T: AppDelegate>(this: &Object, _: Sel, _: id, files: id, s
} }
/// Called when the application's occlusion state has changed. /// Called when the application's occlusion state has changed.
extern fn did_change_occlusion_state<T: AppDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_occlusion_state<T: AppDelegate>(this: &Object, _: Sel, _: id) {
app::<T>(this).occlusion_state_changed(); app::<T>(this).occlusion_state_changed();
} }
/// 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 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()) { match app::<T>(this).delegate_handles_key(key.to_str()) {
@ -305,77 +305,165 @@ pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *co
decl.add_ivar::<usize>(APP_PTR); decl.add_ivar::<usize>(APP_PTR);
// Launching Applications // Launching Applications
decl.add_method(sel!(applicationWillFinishLaunching:), will_finish_launching::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(applicationDidFinishLaunching:), did_finish_launching::<T> as extern fn(&Object, _, _)); 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 // Managing Active Status
decl.add_method(sel!(applicationWillBecomeActive:), will_become_active::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(applicationDidBecomeActive:), did_become_active::<T> as extern fn(&Object, _, _)); sel!(applicationWillBecomeActive:),
decl.add_method(sel!(applicationWillResignActive:), will_resign_active::<T> as extern fn(&Object, _, _)); will_become_active::<T> as extern "C" fn(&Object, _, _)
decl.add_method(sel!(applicationDidResignActive:), did_resign_active::<T> as extern 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 // Terminating Applications
decl.add_method(sel!(applicationShouldTerminate:), should_terminate::<T> as extern fn(&Object, _, _) -> NSUInteger); decl.add_method(
decl.add_method(sel!(applicationWillTerminate:), will_terminate::<T> as extern fn(&Object, _, _)); sel!(applicationShouldTerminate:),
decl.add_method(sel!(applicationShouldTerminateAfterLastWindowClosed:), should_terminate_after_last_window_closed::<T> as extern fn(&Object, _, _) -> BOOL); 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 // Hiding Applications
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern 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 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 fn(&Object, _, _)); decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _));
// Managing Windows // Managing Windows
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern 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 fn(&Object, _, _, BOOL) -> BOOL); decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL
);
// Dock Menu // Dock Menu
decl.add_method(sel!(applicationDockMenu:), dock_menu::<T> as extern fn(&Object, _, _) -> id); decl.add_method(
sel!(applicationDockMenu:),
dock_menu::<T> as extern "C" fn(&Object, _, _) -> id
);
// Displaying Errors // Displaying Errors
decl.add_method(sel!(application:willPresentError:), will_present_error::<T> as extern fn(&Object, _, _, id) -> id); decl.add_method(
sel!(application:willPresentError:),
will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id
);
// Managing the Screen // Managing the Screen
decl.add_method(sel!(applicationDidChangeScreenParameters:), did_change_screen_parameters::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(applicationDidChangeOcclusionState:), did_change_occlusion_state::<T> as extern fn(&Object, _, _)); 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 // User Activities
decl.add_method(sel!(application:willContinueUserActivityWithType:), will_continue_user_activity_with_type::<T> as extern fn(&Object, _, _, id) -> BOOL); decl.add_method(
decl.add_method(sel!(application:continueUserActivity:restorationHandler:), continue_user_activity::<T> as extern fn(&Object, _, _, id, id) -> BOOL); sel!(application:willContinueUserActivityWithType:),
decl.add_method(sel!(application:didFailToContinueUserActivityWithType:error:), failed_to_continue_user_activity::<T> as extern fn(&Object, _, _, id, id)); will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
decl.add_method(sel!(application:didUpdateUserActivity:), did_update_user_activity::<T> as extern fn(&Object, _, _, id)); );
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 // Handling push notifications
decl.add_method(sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:), registered_for_remote_notifications::<T> as extern fn(&Object, _, _, id)); decl.add_method(
decl.add_method(sel!(application:didFailToRegisterForRemoteNotificationsWithError:), failed_to_register_for_remote_notifications::<T> as extern fn(&Object, _, _, id)); sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
decl.add_method(sel!(application:didReceiveRemoteNotification:), did_receive_remote_notification::<T> as extern fn(&Object, _, _, id)); 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 // CloudKit
#[cfg(feature = "cloudkit")] #[cfg(feature = "cloudkit")]
decl.add_method(sel!(application:userDidAcceptCloudKitShareWithMetadata:), accepted_cloudkit_share::<T> as extern fn(&Object, _, _, id)); decl.add_method(
sel!(application:userDidAcceptCloudKitShareWithMetadata:),
accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id)
);
// Opening Files // Opening Files
decl.add_method(sel!(application:openURLs:), open_urls::<T> as extern fn(&Object, _, _, id)); decl.add_method(
decl.add_method(sel!(application:openFileWithoutUI:), open_file_without_ui::<T> as extern fn(&Object, _, _, id) -> BOOL); sel!(application:openURLs:),
decl.add_method(sel!(applicationShouldOpenUntitledFile:), should_open_untitled_file::<T> as extern fn(&Object, _, _) -> BOOL); open_urls::<T> as extern "C" fn(&Object, _, _, id)
decl.add_method(sel!(applicationOpenUntitledFile:), open_untitled_file::<T> as extern fn(&Object, _, _) -> BOOL); );
decl.add_method(sel!(application:openTempFile:), open_temp_file::<T> as extern fn(&Object, _, _, id) -> BOOL); 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 // Printing
decl.add_method(sel!(application:printFile:), print_file::<T> as extern fn(&Object, _, _, id) -> BOOL); decl.add_method(
decl.add_method(sel!(application:printFiles:withSettings:showPrintPanels:), print_files::<T> as extern fn(&Object, _, id, id, id, BOOL) -> NSUInteger); 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 // @TODO: Restoring Application State
// Depends on NSCoder support, which is... welp. // Depends on NSCoder support, which is... welp.
// Scripting // Scripting
decl.add_method(sel!(application:delegateHandlesKey:), delegate_handles_key::<T> as extern fn(&Object, _, _, id) -> BOOL); 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 { unsafe { DELEGATE_CLASS }
DELEGATE_CLASS
}
} }

View file

@ -39,13 +39,13 @@ use std::sync::{Arc, Mutex};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use objc_id::Id;
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, nil, YES, NO, NSUInteger, AutoReleasePool};
use crate::invoker::TargetActionHandler;
use crate::appkit::menu::Menu; use crate::appkit::menu::Menu;
use crate::foundation::{id, nil, AutoReleasePool, NSUInteger, NO, YES};
use crate::invoker::TargetActionHandler;
use crate::notification_center::Dispatcher; use crate::notification_center::Dispatcher;
use crate::utils::activate_cocoa_multithreading; use crate::utils::activate_cocoa_multithreading;
@ -128,7 +128,10 @@ impl<T> App<T> {
} }
} }
impl<T> App<T> where T: AppDelegate + 'static { impl<T> App<T>
where
T: AppDelegate + 'static
{
/// Creates an NSAutoReleasePool, configures various NSApplication properties (e.g, activation /// Creates an NSAutoReleasePool, configures various NSApplication properties (e.g, activation
/// policies), injects an `NSObject` delegate wrapper, and retains everything on the /// policies), injects an `NSObject` delegate wrapper, and retains everything on the
/// Objective-C side of things. /// Objective-C side of things.
@ -151,7 +154,7 @@ impl<T> App<T> where T: AppDelegate + 'static {
let delegate: id = msg_send![delegate_class, new]; let delegate: id = msg_send![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); (&mut *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) Id::from_ptr(delegate)
}; };
@ -180,7 +183,11 @@ impl<T> App<T> where T: AppDelegate + 'static {
// ObjC and such is fast enough that for a large class of applications this is workable. // ObjC and such is fast enough that for a large class of applications this is workable.
// //
// tl;dr: This is all a bit of a hack, and should go away eventually. :) // tl;dr: This is all a bit of a hack, and should go away eventually. :)
impl<T, M> App<T, M> where M: Send + Sync + 'static, T: AppDelegate + Dispatcher<Message = M> { impl<T, M> App<T, M>
where
M: Send + Sync + 'static,
T: AppDelegate + Dispatcher<Message = M>
{
/// Dispatches a message by grabbing the `sharedApplication`, getting ahold of the delegate, /// Dispatches a message by grabbing the `sharedApplication`, getting ahold of the delegate,
/// and passing back through there. /// and passing back through there.
pub fn dispatch_main(message: M) { pub fn dispatch_main(message: M) {
@ -251,7 +258,7 @@ impl App {
pub fn reply_to_open_or_print(response: AppDelegateResponse) { pub fn reply_to_open_or_print(response: AppDelegateResponse) {
shared_application(|app| unsafe { shared_application(|app| unsafe {
let r: NSUInteger = response.into(); let r: NSUInteger = response.into();
let _: () = msg_send![app, replyToOpenOrPrint:r]; let _: () = msg_send![app, replyToOpenOrPrint: r];
}); });
} }
@ -267,14 +274,14 @@ impl App {
for menu in menus.iter_mut() { for menu in menus.iter_mut() {
let item: id = msg_send![item_cls, new]; let item: id = msg_send![item_cls, new];
let _: () = msg_send![item, setSubmenu:&*menu.0]; let _: () = msg_send![item, setSubmenu:&*menu.0];
let _: () = msg_send![main_menu, addItem:item]; let _: () = msg_send![main_menu, addItem: item];
} }
main_menu main_menu
}; };
shared_application(move |app| unsafe { shared_application(move |app| unsafe {
let _: () = msg_send![app, setMainMenu:main_menu]; let _: () = msg_send![app, setMainMenu: main_menu];
}); });
} }
@ -296,7 +303,7 @@ impl App {
/// This is typically called when the user chooses to quit via the App menu. /// This is typically called when the user chooses to quit via the App menu.
pub fn terminate() { pub fn terminate() {
shared_application(|app| unsafe { shared_application(|app| unsafe {
let _: () = msg_send![app, terminate:nil]; let _: () = msg_send![app, terminate: nil];
}); });
} }
} }

View file

@ -35,12 +35,16 @@ pub trait AppDelegate {
fn will_resign_active(&self) {} fn will_resign_active(&self) {}
/// Fired when the user is going to continue an activity. /// Fired when the user is going to continue an activity.
fn will_continue_user_activity(&self, _activity_type: &str) -> bool { false } fn will_continue_user_activity(&self, _activity_type: &str) -> bool {
false
}
/// Fired when data for continuing an activity is available. Currently, the /// Fired when data for continuing an activity is available. Currently, the
/// `restoration_handler` is not used, but there to communicate intent with what this API will /// `restoration_handler` is not used, but there to communicate intent with what this API will
/// eventually be doing. /// eventually be doing.
fn continue_user_activity<F: Fn()>(&self, _activity: UserActivity, _restoration_handler: F) -> bool { false } fn continue_user_activity<F: Fn()>(&self, _activity: UserActivity, _restoration_handler: F) -> bool {
false
}
/// Fired when the activity could not be continued. /// Fired when the activity could not be continued.
fn failed_to_continue_user_activity(&self, _activity_type: &str, _error: Error) {} fn failed_to_continue_user_activity(&self, _activity_type: &str, _error: Error) {}
@ -96,11 +100,15 @@ pub trait AppDelegate {
/// though, you can cancel the termination via `TerminateResponse::Cancel` to continue something essential. If /// though, you can cancel the termination via `TerminateResponse::Cancel` to continue something essential. If
/// you do this, you'll need to be sure to call `App::reply_to_termination_request()` to circle /// you do this, you'll need to be sure to call `App::reply_to_termination_request()` to circle
/// back. /// back.
fn should_terminate(&self) -> TerminateResponse { TerminateResponse::Now } fn should_terminate(&self) -> TerminateResponse {
TerminateResponse::Now
}
/// Called after closing the last open window. Return `true` here if you want /// Called after closing the last open window. Return `true` here if you want
/// the application to terminate. /// the application to terminate.
fn should_terminate_after_last_window_closed(&self) -> bool { false } fn should_terminate_after_last_window_closed(&self) -> bool {
false
}
/// Sent by the application to the delegate prior to default behavior to reopen AppleEvents. /// Sent by the application to the delegate prior to default behavior to reopen AppleEvents.
/// ///
@ -119,16 +127,22 @@ pub trait AppDelegate {
/// ///
/// [Read more /// [Read more
/// here](https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428638-applicationshouldhandlereopen?language=objc) /// here](https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428638-applicationshouldhandlereopen?language=objc)
fn should_handle_reopen(&self, _has_visible_windows: bool) -> bool { true } fn should_handle_reopen(&self, _has_visible_windows: bool) -> bool {
true
}
/// Supply a dock menu for the application dynamically. The default implementation for this /// Supply a dock menu for the application dynamically. The default implementation for this
/// method returns `None`, for no menu. /// method returns `None`, for no menu.
fn dock_menu(&self) -> Option<Menu> { None } fn dock_menu(&self) -> Option<Menu> {
None
}
/// Fired before the application presents an error message to the user. If you find the error /// Fired before the application presents an error message to the user. If you find the error
/// to be... not what you want, you can take it, alter it, and return it anew. The default /// to be... not what you want, you can take it, alter it, and return it anew. The default
/// implementation of this method simply returns the error as-is. /// implementation of this method simply returns the error as-is.
fn will_present_error(&self, error: Error) -> Error { error } fn will_present_error(&self, error: Error) -> Error {
error
}
/// Fired when the screen parameters for the application have changed (e.g, the user changed /// Fired when the screen parameters for the application have changed (e.g, the user changed
/// something in their settings). /// something in their settings).
@ -145,7 +159,7 @@ pub trait AppDelegate {
/// ///
/// Note that since we have this as the de-facto method of handling resource opens, the system /// Note that since we have this as the de-facto method of handling resource opens, the system
/// will _not_ call `application:openFile:` or `application:openFiles`. /// will _not_ call `application:openFile:` or `application:openFiles`.
fn open_urls(&self, _urls: Vec<Url>) { } fn open_urls(&self, _urls: Vec<Url>) {}
/// Fired when the file is requested to be opened programmatically. This is not a commonly used /// Fired when the file is requested to be opened programmatically. This is not a commonly used
/// or implemented method. /// or implemented method.
@ -156,28 +170,38 @@ pub trait AppDelegate {
/// work with the file is under programmatic control of sender, rather than under keyboard control of the user."_ /// work with the file is under programmatic control of sender, rather than under keyboard control of the user."_
/// ///
/// It's unclear how supported this is in sandbox environments, so use at your own risk. /// It's unclear how supported this is in sandbox environments, so use at your own risk.
fn open_file_without_ui(&self, _filename: &str) -> bool { false } fn open_file_without_ui(&self, _filename: &str) -> bool {
false
}
/// Fired when the application is ready and able to open a temporary file. /// Fired when the application is ready and able to open a temporary file.
/// Return `true` or `false` here depending on whether the operation was successful. /// Return `true` or `false` here depending on whether the operation was successful.
/// ///
/// It's your responsibility to remove the temp file. /// It's your responsibility to remove the temp file.
fn open_temp_file(&self, _filename: &str) -> bool { false } fn open_temp_file(&self, _filename: &str) -> bool {
false
}
/// Fired before attempting to open an untitled file. Return `true` here if you want /// Fired before attempting to open an untitled file. Return `true` here if you want
/// `open_untitled_file` to be called by the system. /// `open_untitled_file` to be called by the system.
fn should_open_untitled_file(&self) -> bool { false } fn should_open_untitled_file(&self) -> bool {
false
}
/// Called when the application has asked you to open a new, untitled file. /// Called when the application has asked you to open a new, untitled file.
/// Returns a `bool` indicating whether the file was successfully opened or not. /// Returns a `bool` indicating whether the file was successfully opened or not.
fn open_untitled_file(&self) -> bool { true } fn open_untitled_file(&self) -> bool {
true
}
/// Sent when the user starts up the application on the command line with the -NSPrint option. /// Sent when the user starts up the application on the command line with the -NSPrint option.
/// The application terminates immediately after this method returns. For more information, /// The application terminates immediately after this method returns. For more information,
/// cosnult the official Apple documentation. /// cosnult the official Apple documentation.
/// ///
/// (You probably never need to implement this, but we support it anyway) /// (You probably never need to implement this, but we support it anyway)
fn print_file(&self, _filename: &str) -> bool { false } fn print_file(&self, _filename: &str) -> bool {
false
}
/// Called when the user has requested to print some files. /// Called when the user has requested to print some files.
/// ///
@ -203,5 +227,7 @@ pub trait AppDelegate {
/// Fired when the system wants to know whether your application, via scripting, can handle the /// Fired when the system wants to know whether your application, via scripting, can handle the
/// key specifying operations. /// key specifying operations.
fn delegate_handles_key(&self, _key: &str) -> bool { false } fn delegate_handles_key(&self, _key: &str) -> bool {
false
}
} }

View file

@ -1,6 +1,6 @@
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, YES, NO}; use crate::foundation::{id, NO, YES};
/// Represents a type of cursor that you can associate with mouse movement. /// Represents a type of cursor that you can associate with mouse movement.
/// @TODO: Loading? /// @TODO: Loading?

View file

@ -1,6 +1,6 @@
//! Generic enums that don't fit anywhere else yet. //! Generic enums that don't fit anywhere else yet.
use crate::foundation::{NSUInteger}; use crate::foundation::NSUInteger;
/// Used to set whether and/or how a view or cell draws a focus ring. /// Used to set whether and/or how a view or cell draws a focus ring.
#[derive(Debug)] #[derive(Debug)]

View file

@ -1,9 +1,8 @@
use block::ConcreteBlock; use block::ConcreteBlock;
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::Id;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, nil, NSString}; use crate::foundation::{id, nil, NSString};
@ -23,18 +22,14 @@ pub struct Event(pub Id<Object>);
impl Event { impl Event {
pub(crate) fn new(objc: id) -> Self { pub(crate) fn new(objc: id) -> Self {
Event(unsafe { Event(unsafe { Id::from_ptr(objc) })
Id::from_ptr(objc)
})
} }
pub fn characters(&self) -> String { pub fn characters(&self) -> String {
// @TODO: Check here if key event, invalid otherwise. // @TODO: Check here if key event, invalid otherwise.
// @TODO: Figure out if we can just return &str here, since the Objective-C side // @TODO: Figure out if we can just return &str here, since the Objective-C side
// should... make it work, I think. // should... make it work, I think.
let characters = NSString::retain(unsafe { let characters = NSString::retain(unsafe { msg_send![&*self.0, characters] });
msg_send![&*self.0, characters]
});
characters.to_string() characters.to_string()
} }

View file

@ -6,13 +6,13 @@ use std::fmt;
use std::sync::Once; use std::sync::Once;
use block::ConcreteBlock; use block::ConcreteBlock;
use objc::{class, msg_send, sel, sel_impl};
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, nil, NSString, NSUInteger};
use crate::events::EventModifierFlag; use crate::events::EventModifierFlag;
use crate::foundation::{id, nil, NSString, NSUInteger};
static BLOCK_PTR: &'static str = "cacaoMenuItemBlockPtr"; static BLOCK_PTR: &'static str = "cacaoMenuItemBlockPtr";
@ -30,9 +30,7 @@ impl fmt::Debug for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ptr = format!("{:p}", self.0); let ptr = format!("{:p}", self.0);
f.debug_struct("Action") f.debug_struct("Action").field("fn", &ptr).finish()
.field("fn", &ptr)
.finish()
} }
} }
@ -72,7 +70,7 @@ fn make_menu_item<S: AsRef<str>>(
key_mask = key_mask | y; key_mask = key_mask | y;
} }
let _: () = msg_send![&*item, setKeyEquivalentModifierMask:key_mask]; let _: () = msg_send![&*item, setKeyEquivalentModifierMask: key_mask];
} }
item item
@ -172,7 +170,7 @@ impl MenuItem {
let item = make_menu_item("Services", None, None, None); let item = make_menu_item("Services", None, None, None);
let app: id = msg_send![class!(RSTApplication), sharedApplication]; let app: id = msg_send![class!(RSTApplication), sharedApplication];
let services: id = msg_send![app, servicesMenu]; let services: id = msg_send![app, servicesMenu];
let _: () = msg_send![&*item, setSubmenu:services]; let _: () = msg_send![&*item, setSubmenu: services];
item item
}, },
@ -230,7 +228,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);
@ -251,7 +249,7 @@ impl MenuItem {
} }
unsafe { unsafe {
let _: () = msg_send![&*objc, setKeyEquivalentModifierMask:key_mask]; let _: () = msg_send![&*objc, setKeyEquivalentModifierMask: key_mask];
} }
return MenuItem::Custom(objc); return MenuItem::Custom(objc);
@ -287,7 +285,7 @@ impl MenuItem {
/// On the Objective-C side, we need to ensure our handler is dropped when this subclass /// On the Objective-C side, we need to ensure our handler is dropped when this subclass
/// is deallocated. Note that NSMenuItem is seemingly odd outside of ARC contexts, and we /// is deallocated. Note that NSMenuItem is seemingly odd outside of ARC contexts, and we
/// need to do some extra logic to ensure release calls are properly sent. /// need to do some extra logic to ensure release calls are properly sent.
extern fn dealloc_cacao_menuitem(this: &Object, _: Sel) { extern "C" fn dealloc_cacao_menuitem(this: &Object, _: Sel) {
unsafe { unsafe {
let ptr: usize = *this.get_ivar(BLOCK_PTR); let ptr: usize = *this.get_ivar(BLOCK_PTR);
let obj = ptr as *mut Action; let obj = ptr as *mut Action;
@ -305,7 +303,7 @@ extern fn dealloc_cacao_menuitem(this: &Object, _: Sel) {
} }
/// Called when our custom item needs to fire. /// Called when our custom item needs to fire.
extern fn fire_block_action(this: &Object, _: Sel, _item: id) { extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) {
let action = crate::utils::load::<Action>(this, BLOCK_PTR); let action = crate::utils::load::<Action>(this, BLOCK_PTR);
(action.0)(); (action.0)();
} }
@ -324,13 +322,11 @@ pub(crate) fn register_menu_item_class() -> *const Class {
let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap(); let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap();
decl.add_ivar::<usize>(BLOCK_PTR); decl.add_ivar::<usize>(BLOCK_PTR);
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern fn(&Object, _)); decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern fn(&Object, _, id)); decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
APP_CLASS = decl.register(); APP_CLASS = decl.register();
}); });
unsafe { unsafe { APP_CLASS }
APP_CLASS
}
} }

View file

@ -2,12 +2,12 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use objc_id::{Id, ShareId};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::{Id, ShareId};
use crate::foundation::{id, NSInteger, NSString};
use crate::appkit::menu::item::MenuItem; use crate::appkit::menu::item::MenuItem;
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.
@ -55,8 +55,8 @@ impl Menu {
while count != 0 { while count != 0 {
count -= 1; count -= 1;
let item: id = msg_send![menu, itemAtIndex:count]; let item: id = msg_send![menu, itemAtIndex: count];
let _: () = msg_send![menu, removeItemAtIndex:count]; let _: () = msg_send![menu, removeItemAtIndex: count];
let _: () = msg_send![item, release]; let _: () = msg_send![item, release];
} }
} }
@ -82,13 +82,9 @@ impl Menu {
MenuItem::HideOthers, MenuItem::HideOthers,
MenuItem::ShowAll, MenuItem::ShowAll,
MenuItem::Separator, MenuItem::Separator,
MenuItem::Quit MenuItem::Quit,
]), ]),
Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("File", vec![
MenuItem::CloseWindow
]),
Menu::new("Edit", vec![ Menu::new("Edit", vec![
MenuItem::Undo, MenuItem::Undo,
MenuItem::Redo, MenuItem::Redo,
@ -97,19 +93,15 @@ impl Menu {
MenuItem::Copy, MenuItem::Copy,
MenuItem::Paste, MenuItem::Paste,
MenuItem::Separator, MenuItem::Separator,
MenuItem::SelectAll MenuItem::SelectAll,
]), ]),
Menu::new("View", vec![MenuItem::EnterFullScreen]),
Menu::new("View", vec![
MenuItem::EnterFullScreen
]),
Menu::new("Window", vec![ Menu::new("Window", vec![
MenuItem::Minimize, MenuItem::Minimize,
MenuItem::Zoom, MenuItem::Zoom,
MenuItem::Separator, MenuItem::Separator,
MenuItem::new("Bring All to Front") MenuItem::new("Bring All to Front"),
]) ]),
] ]
} }
} }

View file

@ -4,28 +4,18 @@ use std::sync::Once;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl, msg_send}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{load_or_register_class, id, BOOL, NSArray, NSString}; use crate::appkit::toolbar::{ToolbarDelegate, TOOLBAR_PTR};
use crate::appkit::toolbar::{TOOLBAR_PTR, ToolbarDelegate}; use crate::foundation::{id, load_or_register_class, NSArray, NSString, BOOL};
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.
extern fn allowed_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id { extern "C" fn allowed_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id {
let toolbar = load::<T>(this, TOOLBAR_PTR); let toolbar = load::<T>(this, TOOLBAR_PTR);
let identifiers: NSArray = toolbar.allowed_item_identifiers().iter().map(|identifier| { let identifiers: NSArray = toolbar
identifier.to_nsstring() .allowed_item_identifiers()
}).collect::<Vec<id>>().into();
identifiers.into()
}
/// Retrieves and passes the default item identifiers for this toolbar.
extern fn default_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id {
let toolbar = load::<T>(this, TOOLBAR_PTR);
let identifiers: NSArray = toolbar.default_item_identifiers()
.iter() .iter()
.map(|identifier| identifier.to_nsstring()) .map(|identifier| identifier.to_nsstring())
.collect::<Vec<id>>() .collect::<Vec<id>>()
@ -35,10 +25,25 @@ extern fn default_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _:
} }
/// Retrieves and passes the default item identifiers for this toolbar. /// Retrieves and passes the default item identifiers for this toolbar.
extern fn selectable_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id { extern "C" fn default_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id {
let toolbar = load::<T>(this, TOOLBAR_PTR); let toolbar = load::<T>(this, TOOLBAR_PTR);
let identifiers: NSArray = toolbar.selectable_item_identifiers() let identifiers: NSArray = toolbar
.default_item_identifiers()
.iter()
.map(|identifier| identifier.to_nsstring())
.collect::<Vec<id>>()
.into();
identifiers.into()
}
/// Retrieves and passes the default item identifiers for this toolbar.
extern "C" fn selectable_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel, _: id) -> id {
let toolbar = load::<T>(this, TOOLBAR_PTR);
let identifiers: NSArray = toolbar
.selectable_item_identifiers()
.iter() .iter()
.map(|identifier| identifier.to_nsstring()) .map(|identifier| identifier.to_nsstring())
.collect::<Vec<id>>() .collect::<Vec<id>>()
@ -49,20 +54,12 @@ extern fn selectable_item_identifiers<T: ToolbarDelegate>(this: &Object, _: Sel,
/// 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 fn item_for_identifier<T: ToolbarDelegate>( extern "C" fn item_for_identifier<T: ToolbarDelegate>(this: &Object, _: Sel, _: id, identifier: id, _: BOOL) -> id {
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::from_retained(identifier);
let item = toolbar.item_for(identifier.to_str()); let item = toolbar.item_for(identifier.to_str());
unsafe { unsafe { msg_send![&*item.objc, self] }
msg_send![&*item.objc, self]
}
//&mut *item.objc //&mut *item.objc
} }
@ -76,19 +73,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 fn(&Object, _, _) -> id allowed_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
); );
decl.add_method( decl.add_method(
sel!(toolbarDefaultItemIdentifiers:), sel!(toolbarDefaultItemIdentifiers:),
default_item_identifiers::<T> as extern fn(&Object, _, _) -> id default_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
); );
decl.add_method( decl.add_method(
sel!(toolbarSelectableItemIdentifiers:), sel!(toolbarSelectableItemIdentifiers:),
selectable_item_identifiers::<T> as extern fn(&Object, _, _) -> id selectable_item_identifiers::<T> as extern "C" fn(&Object, _, _) -> id
); );
decl.add_method( decl.add_method(
sel!(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:), sel!(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:),
item_for_identifier::<T> as extern fn(&Object, _, _, _, _) -> id item_for_identifier::<T> as extern "C" fn(&Object, _, _, _, _) -> id
); );
}) })
} }

View file

@ -3,17 +3,17 @@
//! //!
//! UNFORTUNATELY, this is a very old and janky API. So... yeah. //! UNFORTUNATELY, this is a very old and janky API. So... yeah.
use std::fmt;
use core_graphics::geometry::CGSize; use core_graphics::geometry::CGSize;
use std::fmt;
use objc_id::{Id, ShareId};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::{Id, ShareId};
use crate::foundation::{id, YES, NO, NSString}; use crate::button::{BezelStyle, Button};
use crate::invoker::TargetActionHandler; use crate::foundation::{id, NSString, NO, YES};
use crate::button::{Button, BezelStyle};
use crate::image::Image; use crate::image::Image;
use crate::invoker::TargetActionHandler;
/// Wraps `NSToolbarItem`. Enables configuring things like size, view, and so on. /// Wraps `NSToolbarItem`. Enables configuring things like size, view, and so on.
#[derive(Debug)] #[derive(Debug)]
@ -34,7 +34,7 @@ impl ToolbarItem {
let objc = unsafe { let objc = unsafe {
let identifr = NSString::new(&identifier); let identifr = NSString::new(&identifier);
let alloc: id = msg_send![class!(NSToolbarItem), alloc]; let alloc: id = msg_send![class!(NSToolbarItem), alloc];
let item: id = msg_send![alloc, initWithItemIdentifier:identifr]; let item: id = msg_send![alloc, initWithItemIdentifier: identifr];
Id::from_ptr(item) Id::from_ptr(item)
}; };
@ -70,7 +70,7 @@ impl ToolbarItem {
button.set_bezel_style(BezelStyle::TexturedRounded); button.set_bezel_style(BezelStyle::TexturedRounded);
button.objc.with_mut(|obj| unsafe { button.objc.with_mut(|obj| unsafe {
let _: () = msg_send![&*self.objc, setView:obj]; let _: () = msg_send![&*self.objc, setView: obj];
}); });
self.button = Some(button); self.button = Some(button);
@ -89,7 +89,7 @@ impl ToolbarItem {
pub fn set_min_size(&mut self, width: f64, height: f64) { pub fn set_min_size(&mut self, width: f64, height: f64) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setMinSize:size]; let _: () = msg_send![&*self.objc, setMinSize: size];
} }
} }
@ -97,7 +97,7 @@ impl ToolbarItem {
pub fn set_max_size(&mut self, width: f64, height: f64) { pub fn set_max_size(&mut self, width: f64, height: f64) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setMaxSize:size]; let _: () = msg_send![&*self.objc, setMaxSize: size];
} }
} }

View file

@ -5,11 +5,11 @@
use std::fmt; use std::fmt;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSString, NSUInteger}; use crate::foundation::{id, nil, NSString, NSUInteger, NO, YES};
mod class; mod class;
use class::register_toolbar_class; use class::register_toolbar_class;
@ -21,7 +21,7 @@ mod traits;
pub use traits::ToolbarDelegate; pub use traits::ToolbarDelegate;
mod enums; mod enums;
pub use enums::{ToolbarDisplayMode, ToolbarSizeMode, ItemIdentifier}; pub use enums::{ItemIdentifier, ToolbarDisplayMode, ToolbarSizeMode};
pub(crate) static TOOLBAR_PTR: &str = "cacaoToolbarPtr"; pub(crate) static TOOLBAR_PTR: &str = "cacaoToolbarPtr";
@ -41,7 +41,10 @@ pub struct Toolbar<T = ()> {
pub delegate: Option<Box<T>> pub delegate: Option<Box<T>>
} }
impl<T> Toolbar<T> where T: ToolbarDelegate + 'static { impl<T> Toolbar<T>
where
T: ToolbarDelegate + 'static
{
/// Creates a new `NSToolbar` instance, configures it appropriately, sets up the delegate /// Creates a new `NSToolbar` instance, configures it appropriately, sets up the delegate
/// chain, and retains it all. /// chain, and retains it all.
pub fn new<S: Into<String>>(identifier: S, delegate: T) -> Self { pub fn new<S: Into<String>>(identifier: S, delegate: T) -> Self {
@ -52,12 +55,12 @@ impl<T> Toolbar<T> where T: ToolbarDelegate + 'static {
let (objc, objc_delegate) = unsafe { let (objc, objc_delegate) = unsafe {
let alloc: id = msg_send![class!(NSToolbar), alloc]; let alloc: id = msg_send![class!(NSToolbar), alloc];
let identifier = NSString::new(&identifier); let identifier = NSString::new(&identifier);
let toolbar: id = msg_send![alloc, initWithIdentifier:identifier]; let toolbar: id = msg_send![alloc, initWithIdentifier: identifier];
let objc_delegate: id = msg_send![cls, new]; //WithIdentifier:identifier]; let objc_delegate: id = msg_send![cls, new]; //WithIdentifier:identifier];
let ptr: *const T = &*delegate; let ptr: *const T = &*delegate;
(&mut *objc_delegate).set_ivar(TOOLBAR_PTR, ptr as usize); (&mut *objc_delegate).set_ivar(TOOLBAR_PTR, ptr as usize);
let _: () = msg_send![toolbar, setDelegate:objc_delegate]; let _: () = msg_send![toolbar, setDelegate: objc_delegate];
(ShareId::from_ptr(toolbar), ShareId::from_ptr(objc_delegate)) (ShareId::from_ptr(toolbar), ShareId::from_ptr(objc_delegate))
}; };
@ -73,7 +76,7 @@ impl<T> Toolbar<T> where T: ToolbarDelegate + 'static {
identifier, identifier,
objc, objc,
objc_delegate, objc_delegate,
delegate: Some(delegate), delegate: Some(delegate)
} }
} }
} }
@ -95,7 +98,7 @@ impl<T> Toolbar<T> {
let mode: NSUInteger = mode.into(); let mode: NSUInteger = mode.into();
unsafe { unsafe {
let _: () = msg_send![&*self.objc, setDisplayMode:mode]; let _: () = msg_send![&*self.objc, setDisplayMode: mode];
} }
} }
@ -104,7 +107,7 @@ impl<T> Toolbar<T> {
let mode: NSUInteger = mode.into(); let mode: NSUInteger = mode.into();
unsafe { unsafe {
let _: () = msg_send![&*self.objc, setSizeMode:mode]; let _: () = msg_send![&*self.objc, setSizeMode: mode];
} }
} }
@ -150,7 +153,7 @@ impl<T> Drop for Toolbar<T> {
fn drop(&mut self) { fn drop(&mut self) {
if self.delegate.is_some() { if self.delegate.is_some() {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, setDelegate:nil]; let _: () = msg_send![&*self.objc, setDelegate: nil];
} }
} }
} }

View file

@ -2,7 +2,7 @@
//! go. Currently a bit incomplete in that we don't support the customizing workflow, but feel free //! go. Currently a bit incomplete in that we don't support the customizing workflow, but feel free
//! to pull request it. //! to pull request it.
use crate::appkit::toolbar::{Toolbar, ToolbarItem, ItemIdentifier}; use crate::appkit::toolbar::{ItemIdentifier, Toolbar, ToolbarItem};
/// A trait that you can implement to have your struct/etc act as an `NSToolbarDelegate`. /// A trait that you can implement to have your struct/etc act as an `NSToolbarDelegate`.
pub trait ToolbarDelegate { pub trait ToolbarDelegate {
@ -30,7 +30,9 @@ pub trait ToolbarDelegate {
/// The default items in this toolbar. This defaults to a blank `Vec`, and is an optional /// The default items in this toolbar. This defaults to a blank `Vec`, and is an optional
/// method - mostly useful for Preferences windows. /// method - mostly useful for Preferences windows.
fn selectable_item_identifiers(&self) -> Vec<ItemIdentifier> { vec![] } fn selectable_item_identifiers(&self) -> Vec<ItemIdentifier> {
vec![]
}
/// For a given `identifier`, return the `ToolbarItem` that should be displayed. /// For a given `identifier`, return the `ToolbarItem` that should be displayed.
fn item_for(&self, _identifier: &str) -> &ToolbarItem; fn item_for(&self, _identifier: &str) -> &ToolbarItem;

View file

@ -9,13 +9,13 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use crate::foundation::{load_or_register_class, id, BOOL, YES, NO, NSUInteger};
use crate::utils::{load, CGSize};
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::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 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() { match window.should_close() {
@ -26,37 +26,37 @@ extern fn should_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) -> BOOL
/// 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 fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_close(); window.will_close();
} }
/// Called when an `NSWindowDelegate` receives a `windowWillMove:` event. /// Called when an `NSWindowDelegate` receives a `windowWillMove:` event.
extern fn will_move<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_move<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_move(); window.will_move();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidMove:` event. /// Called when an `NSWindowDelegate` receives a `windowDidMove:` event.
extern fn did_move<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_move<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_move(); window.did_move();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_change_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_change_screen(); window.did_change_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_change_screen_profile<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_screen_profile<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_change_screen_profile(); window.did_change_screen_profile();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize { extern "C" fn will_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let s = window.will_resize(size.width as f64, size.height as f64); let s = window.will_resize(size.width as f64, size.height as f64);
@ -67,61 +67,58 @@ extern fn will_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGS
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_resize(); window.did_resize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_start_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_start_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_start_live_resize(); window.will_start_live_resize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_end_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_end_live_resize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_end_live_resize(); window.did_end_live_resize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn will_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_miniaturize(); window.will_miniaturize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_miniaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_miniaturize(); window.did_miniaturize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event.
extern fn did_deminiaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_deminiaturize<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_deminiaturize(); window.did_deminiaturize();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn will_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_enter_full_screen(); window.will_enter_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_enter_full_screen(); window.did_enter_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn content_size_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize { extern "C" fn content_size_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, size: CGSize) -> CGSize {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let (width, height) = window.content_size_for_full_screen( let (width, height) = window.content_size_for_full_screen(size.width as f64, size.height as f64);
size.width as f64,
size.height as f64
);
CGSize { CGSize {
width: width as CGFloat, width: width as CGFloat,
@ -130,7 +127,7 @@ extern fn content_size_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel,
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn options_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, options: NSUInteger) -> NSUInteger { extern "C" fn options_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id, options: NSUInteger) -> NSUInteger {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
let desired_opts = window.presentation_options_for_full_screen(); let desired_opts = window.presentation_options_for_full_screen();
@ -148,73 +145,73 @@ extern fn options_for_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: i
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn will_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn will_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.will_exit_full_screen(); window.will_exit_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_exit_full_screen(); window.did_exit_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_fail_to_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_fail_to_enter_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_fail_to_enter_full_screen(); window.did_fail_to_enter_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event.
extern fn did_fail_to_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_fail_to_exit_full_screen<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_fail_to_exit_full_screen(); window.did_fail_to_exit_full_screen();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event.
extern fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_backing_properties<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_change_backing_properties(); window.did_change_backing_properties();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event. /// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event.
extern fn did_change_occlusion_state<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_change_occlusion_state<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_change_occlusion_state(); window.did_change_occlusion_state();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidUpdate:` event. /// Called when an `NSWindowDelegate` receives a `windowDidUpdate:` event.
extern fn did_update<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_update<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_update(); window.did_update();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event. /// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_become_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_become_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_become_main(); window.did_become_main();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event. /// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_resign_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_resign_main<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_resign_main(); window.did_resign_main();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event. /// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_become_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_become_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_become_key(); window.did_become_key();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event. /// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_resign_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_resign_key<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_resign_key(); window.did_resign_key();
} }
/// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event. /// Called when an `NSWindowDelegate` receives a `windowDidExpose:` event.
extern fn did_expose<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn did_expose<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.did_expose(); window.did_expose();
} }
@ -223,7 +220,7 @@ extern fn did_expose<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
/// delegate returns `true` in `should_cancel_on_esc`, then this will allow your /// delegate returns `true` in `should_cancel_on_esc`, then this will allow your
/// window to close when the Esc key is hit. This is mostly useful for Sheet-presented /// window to close when the Esc key is hit. This is mostly useful for Sheet-presented
/// windows, and so the default response from delegates is `false` and must be opted in to. /// windows, and so the default response from delegates is `false` and must be opted in to.
extern fn cancel<T: WindowDelegate>(this: &Object, _: Sel, _: id) { extern "C" fn cancel<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR); let window = load::<T>(this, WINDOW_DELEGATE_PTR);
window.cancel(); window.cancel();
} }
@ -235,49 +232,112 @@ pub(crate) fn register_window_class_with_delegate<T: WindowDelegate>(instance: &
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR); decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
// NSWindowDelegate methods // NSWindowDelegate methods
decl.add_method(sel!(windowShouldClose:), should_close::<T> as extern fn(&Object, _, _) -> BOOL); decl.add_method(
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern fn(&Object, _, _)); sel!(windowShouldClose:),
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(sel!(windowWillResize:toSize:), will_resize::<T> as extern fn(&Object, _, _, CGSize) -> CGSize); decl.add_method(
decl.add_method(sel!(windowDidResize:), did_resize::<T> as extern fn(&Object, _, _)); sel!(windowWillResize:toSize:),
decl.add_method(sel!(windowWillStartLiveResize:), will_start_live_resize::<T> as extern fn(&Object, _, _)); will_resize::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize
decl.add_method(sel!(windowDidEndLiveResize:), did_end_live_resize::<T> as extern fn(&Object, _, _)); );
decl.add_method(sel!(windowDidResize:), did_resize::<T> as extern "C" fn(&Object, _, _));
decl.add_method(
sel!(windowWillStartLiveResize:),
will_start_live_resize::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidEndLiveResize:),
did_end_live_resize::<T> as extern "C" fn(&Object, _, _)
);
// Minimizing // Minimizing
decl.add_method(sel!(windowWillMiniaturize:), will_miniaturize::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(windowDidMiniaturize:), did_miniaturize::<T> as extern fn(&Object, _, _)); sel!(windowWillMiniaturize:),
decl.add_method(sel!(windowDidDeminiaturize:), did_deminiaturize::<T> as extern fn(&Object, _, _)); will_miniaturize::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidMiniaturize:),
did_miniaturize::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidDeminiaturize:),
did_deminiaturize::<T> as extern "C" fn(&Object, _, _)
);
// Full Screen // Full Screen
decl.add_method(sel!(window:willUseFullScreenContentSize:), content_size_for_full_screen::<T> as extern fn(&Object, _, _, CGSize) -> CGSize); decl.add_method(
decl.add_method(sel!(window:willUseFullScreenPresentationOptions:), options_for_full_screen::<T> as extern fn(&Object, _, _, NSUInteger) -> NSUInteger); sel!(window:willUseFullScreenContentSize:),
decl.add_method(sel!(windowWillEnterFullScreen:), will_enter_full_screen::<T> as extern fn(&Object, _, _)); content_size_for_full_screen::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize
decl.add_method(sel!(windowDidEnterFullScreen:), did_enter_full_screen::<T> as extern fn(&Object, _, _)); );
decl.add_method(sel!(windowWillExitFullScreen:), will_exit_full_screen::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(windowDidExitFullScreen:), did_exit_full_screen::<T> as extern fn(&Object, _, _)); sel!(window:willUseFullScreenPresentationOptions:),
decl.add_method(sel!(windowDidFailToEnterFullScreen:), did_fail_to_enter_full_screen::<T> as extern fn(&Object, _, _)); options_for_full_screen::<T> as extern "C" fn(&Object, _, _, NSUInteger) -> NSUInteger
decl.add_method(sel!(windowDidFailToExitFullScreen:), did_fail_to_exit_full_screen::<T> as extern fn(&Object, _, _)); );
decl.add_method(
sel!(windowWillEnterFullScreen:),
will_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidEnterFullScreen:),
did_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowWillExitFullScreen:),
will_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidExitFullScreen:),
did_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidFailToEnterFullScreen:),
did_fail_to_enter_full_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidFailToExitFullScreen:),
did_fail_to_exit_full_screen::<T> as extern "C" fn(&Object, _, _)
);
// Key status // Key status
decl.add_method(sel!(windowDidBecomeKey:), did_become_key::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidBecomeKey:), did_become_key::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(windowDidResignKey:), did_resign_key::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidResignKey:), did_resign_key::<T> as extern "C" fn(&Object, _, _));
// Main status // Main status
decl.add_method(sel!(windowDidBecomeMain:), did_become_main::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(windowDidResignMain:), did_resign_main::<T> as extern fn(&Object, _, _)); sel!(windowDidBecomeMain:),
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 fn(&Object, _, _)); decl.add_method(sel!(windowWillMove:), will_move::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(windowDidMove:), did_move::<T> as extern fn(&Object, _, _)); decl.add_method(sel!(windowDidMove:), did_move::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(windowDidChangeScreen:), did_change_screen::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(windowDidChangeScreenProfile:), did_change_screen_profile::<T> as extern fn(&Object, _, _)); sel!(windowDidChangeScreen:),
decl.add_method(sel!(windowDidChangeBackingProperties:), did_change_backing_properties::<T> as extern fn(&Object, _, _)); did_change_screen::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidChangeScreenProfile:),
did_change_screen_profile::<T> as extern "C" fn(&Object, _, _)
);
decl.add_method(
sel!(windowDidChangeBackingProperties:),
did_change_backing_properties::<T> as extern "C" fn(&Object, _, _)
);
// Random // Random
decl.add_method(sel!(windowDidChangeOcclusionState:), did_change_occlusion_state::<T> as extern fn(&Object, _, _)); decl.add_method(
decl.add_method(sel!(windowDidExpose:), did_expose::<T> as extern fn(&Object, _, _)); sel!(windowDidChangeOcclusionState:),
decl.add_method(sel!(windowDidUpdate:), did_update::<T> as extern fn(&Object, _, _)); did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
decl.add_method(sel!(cancelOperation:), cancel::<T> as extern fn (&Object, _, _)); );
decl.add_method(sel!(windowDidExpose:), did_expose::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(windowDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(cancelOperation:), cancel::<T> as extern "C" fn(&Object, _, _));
}) })
} }

View file

@ -2,9 +2,9 @@
//! mask). This configuration object acts as a way to orchestrate enabling customization before the //! mask). This configuration object acts as a way to orchestrate enabling customization before the
//! window object is created - it's returned in your `WindowDelegate` object. //! window object is created - it's returned in your `WindowDelegate` object.
use crate::appkit::window::enums::{WindowStyle, WindowToolbarStyle};
use crate::foundation::NSUInteger; use crate::foundation::NSUInteger;
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::appkit::window::enums::{WindowStyle, WindowToolbarStyle};
#[derive(Debug)] #[derive(Debug)]
pub struct WindowConfig { pub struct WindowConfig {
@ -45,8 +45,12 @@ impl Default for WindowConfig {
}; };
config.set_styles(&[ config.set_styles(&[
WindowStyle::Resizable, WindowStyle::Miniaturizable, WindowStyle::UnifiedTitleAndToolbar, WindowStyle::Resizable,
WindowStyle::Closable, WindowStyle::Titled, WindowStyle::FullSizeContentView WindowStyle::Miniaturizable,
WindowStyle::UnifiedTitleAndToolbar,
WindowStyle::Closable,
WindowStyle::Titled,
WindowStyle::FullSizeContentView
]); ]);
config config

View file

@ -3,9 +3,9 @@
use std::sync::Once; use std::sync::Once;
use objc::class;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::Class; use objc::runtime::Class;
use objc::class;
use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
@ -22,7 +22,5 @@ pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Cl
DELEGATE_CLASS = decl.register(); DELEGATE_CLASS = decl.register();
}); });
unsafe { unsafe { DELEGATE_CLASS }
DELEGATE_CLASS
}
} }

View file

@ -33,9 +33,9 @@ use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::appkit::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
use crate::foundation::{id, nil}; use crate::foundation::{id, nil};
use crate::utils::Controller; use crate::utils::Controller;
use crate::appkit::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
mod class; mod class;
use class::register_window_controller_class; use class::register_window_controller_class;
@ -50,7 +50,10 @@ pub struct WindowController<T> {
pub window: Window<T> pub window: Window<T>
} }
impl<T> WindowController<T> where T: WindowDelegate + 'static { impl<T> WindowController<T>
where
T: WindowDelegate + 'static
{
/// Allocates and configures an `NSWindowController` in the Objective-C/Cocoa runtime that maps over /// Allocates and configures an `NSWindowController` in the Objective-C/Cocoa runtime that maps over
/// to your supplied delegate. /// to your supplied delegate.
pub fn with(config: WindowConfig, delegate: T) -> Self { pub fn with(config: WindowConfig, delegate: T) -> Self {
@ -84,7 +87,7 @@ impl<T> WindowController<T> where T: WindowDelegate + 'static {
/// Shows the window, running a configuration pass if necessary. /// Shows the window, running a configuration pass if necessary.
pub fn show(&self) { pub fn show(&self) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, showWindow:nil]; let _: () = msg_send![&*self.objc, showWindow: nil];
} }
} }
@ -98,8 +101,6 @@ impl<T> WindowController<T> where T: WindowDelegate + 'static {
impl<T> fmt::Debug for WindowController<T> { impl<T> fmt::Debug for WindowController<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("WindowController") f.debug_struct("WindowController").field("objc", &self.objc).finish()
.field("objc", &self.objc)
.finish()
} }
} }

View file

@ -13,13 +13,13 @@ 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::{msg_send, sel, sel_impl, class};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::appkit::toolbar::{Toolbar, ToolbarDelegate}; use crate::appkit::toolbar::{Toolbar, ToolbarDelegate};
use crate::color::Color; use crate::color::Color;
use crate::foundation::{id, nil, to_bool, YES, NO, NSString, NSInteger, NSUInteger}; use crate::foundation::{id, nil, to_bool, NSInteger, NSString, NSUInteger, NO, YES};
use crate::layout::Layout; use crate::layout::Layout;
use crate::objc_access::ObjcAccess; use crate::objc_access::ObjcAccess;
use crate::utils::{os, Controller}; use crate::utils::{os, Controller};
@ -69,7 +69,7 @@ impl Window {
let objc = unsafe { let objc = 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!(NSWindow), alloc]; let alloc: id = msg_send![class!(NSWindow), alloc];
@ -92,16 +92,16 @@ impl Window {
// 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) ShareId::from_ptr(window)
@ -114,7 +114,10 @@ impl Window {
} }
} }
impl<T> Window<T> where T: WindowDelegate + 'static { impl<T> Window<T>
where
T: WindowDelegate + 'static
{
/// Constructs a new Window with a `config` and `delegate`. Using a `WindowDelegate` enables /// Constructs a new Window with a `config` and `delegate`. Using a `WindowDelegate` enables
/// you to respond to window lifecycle events - visibility, movement, and so on. It also /// you to respond to window lifecycle events - visibility, movement, and so on. It also
/// enables easier structure of your codebase, and in a way simulates traditional class based /// enables easier structure of your codebase, and in a way simulates traditional class based
@ -126,7 +129,7 @@ impl<T> Window<T> where T: WindowDelegate + 'static {
let objc = unsafe { let objc = 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]; let alloc: id = msg_send![class, alloc];
@ -152,19 +155,19 @@ impl<T> Window<T> where T: WindowDelegate + 'static {
// 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) ShareId::from_ptr(window)
@ -190,7 +193,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];
} }
} }
@ -198,7 +201,7 @@ impl<T> Window<T> {
pub fn set_title_visibility(&self, visibility: TitleVisibility) { pub fn set_title_visibility(&self, visibility: TitleVisibility) {
unsafe { unsafe {
let v = NSInteger::from(visibility); let v = NSInteger::from(visibility);
let _: () = msg_send![&*self.objc, setTitleVisibility:v]; let _: () = msg_send![&*self.objc, setTitleVisibility: v];
} }
} }
@ -226,7 +229,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];
} }
} }
@ -234,7 +237,7 @@ impl<T> Window<T> {
pub fn set_content_size<F: Into<f64>>(&self, width: F, height: F) { pub fn set_content_size<F: Into<f64>>(&self, width: F, height: F) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setContentSize:size]; let _: () = msg_send![&*self.objc, setContentSize: size];
} }
} }
@ -242,7 +245,7 @@ impl<T> Window<T> {
pub fn set_minimum_content_size<F: Into<f64>>(&self, width: F, height: F) { pub fn set_minimum_content_size<F: Into<f64>>(&self, width: F, height: F) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setContentMinSize:size]; let _: () = msg_send![&*self.objc, setContentMinSize: size];
} }
} }
@ -250,7 +253,7 @@ impl<T> Window<T> {
pub fn set_maximum_content_size<F: Into<f64>>(&self, width: F, height: F) { pub fn set_maximum_content_size<F: Into<f64>>(&self, width: F, height: F) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setContentMaxSize:size]; let _: () = msg_send![&*self.objc, setContentMaxSize: size];
} }
} }
@ -258,7 +261,7 @@ impl<T> Window<T> {
pub fn set_minimum_size<F: Into<f64>>(&self, width: F, height: F) { pub fn set_minimum_size<F: Into<f64>>(&self, width: F, height: F) {
unsafe { unsafe {
let size = CGSize::new(width.into(), height.into()); let size = CGSize::new(width.into(), height.into());
let _: () = msg_send![&*self.objc, setMinSize:size]; let _: () = msg_send![&*self.objc, setMinSize: size];
} }
} }
@ -273,7 +276,7 @@ impl<T> Window<T> {
/// this window. /// this window.
pub fn toggle_toolbar_shown(&self) { pub fn toggle_toolbar_shown(&self) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, toggleToolbarShown:nil]; let _: () = msg_send![&*self.objc, toggleToolbarShown: nil];
} }
} }
@ -307,7 +310,7 @@ impl<T> Window<T> {
/// Shows the window. /// Shows the window.
pub fn show(&self) { pub fn show(&self) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, makeKeyAndOrderFront:nil]; let _: () = msg_send![&*self.objc, makeKeyAndOrderFront: nil];
} }
} }
@ -324,7 +327,7 @@ impl<T> Window<T> {
/// Toggles a Window being full screen or not. /// Toggles a Window being full screen or not.
pub fn toggle_full_screen(&self) { pub fn toggle_full_screen(&self) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, toggleFullScreen:nil]; let _: () = msg_send![&*self.objc, toggleFullScreen: nil];
} }
} }
@ -333,22 +336,18 @@ impl<T> Window<T> {
let color: id = color.as_ref().into(); let color: id = color.as_ref().into();
unsafe { unsafe {
let _: () = msg_send![&*self.objc, setBackgroundColor:color]; let _: () = msg_send![&*self.objc, setBackgroundColor: color];
} }
} }
/// Returns whether this window is opaque or not. /// Returns whether this window is opaque or not.
pub fn is_opaque(&self) -> bool { pub fn is_opaque(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isOpaque] })
msg_send![&*self.objc, isOpaque]
})
} }
/// Returns whether this window is miniaturized or not. /// Returns whether this window is miniaturized or not.
pub fn is_miniaturized(&self) -> bool { pub fn is_miniaturized(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isMiniaturized] })
msg_send![&*self.objc, isMiniaturized]
})
} }
/// Miniaturize this window. /// Miniaturize this window.
@ -382,30 +381,22 @@ impl<T> Window<T> {
/// space. For nonvisible windows, it indicates whether ordering the window onscreen would cause it to /// space. For nonvisible windows, it indicates whether ordering the window onscreen would cause it to
/// be on the active space._ /// be on the active space._
pub fn is_on_active_space(&self) -> bool { pub fn is_on_active_space(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isOnActiveSpace] })
msg_send![&*self.objc, isOnActiveSpace]
})
} }
/// Returns whether this window is visible or not. /// Returns whether this window is visible or not.
pub fn is_visible(&self) -> bool { pub fn is_visible(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isVisible] })
msg_send![&*self.objc, isVisible]
})
} }
/// Returns whether this window is the key or not. /// Returns whether this window is the key or not.
pub fn is_key(&self) -> bool { pub fn is_key(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isKeyWindow] })
msg_send![&*self.objc, isKeyWindow]
})
} }
/// Returns whether this window can become the key window. /// Returns whether this window can become the key window.
pub fn can_become_key(&self) -> bool { pub fn can_become_key(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, canBecomeKeyWindow] })
msg_send![&*self.objc, canBecomeKeyWindow]
})
} }
/// Make this window the key window. /// Make this window the key window.
@ -419,22 +410,18 @@ impl<T> Window<T> {
/// you. /// you.
pub fn make_key_and_order_front(&self) { pub fn make_key_and_order_front(&self) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, makeKeyAndOrderFront:nil]; let _: () = msg_send![&*self.objc, makeKeyAndOrderFront: nil];
} }
} }
/// Returns if this is the main window or not. /// Returns if this is the main window or not.
pub fn is_main_window(&self) -> bool { pub fn is_main_window(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, isMainWindow] })
msg_send![&*self.objc, isMainWindow]
})
} }
/// Returns if this can become the main window. /// Returns if this can become the main window.
pub fn can_become_main_window(&self) -> bool { pub fn can_become_main_window(&self) -> bool {
to_bool(unsafe { to_bool(unsafe { msg_send![&*self.objc, canBecomeMainWindow] })
msg_send![&*self.objc, canBecomeMainWindow]
})
} }
/// Set whether this window should be excluded from the top-level "Windows" menu. /// Set whether this window should be excluded from the top-level "Windows" menu.
@ -450,7 +437,7 @@ impl<T> Window<T> {
/// Sets the separator style for this window. /// Sets the separator style for this window.
pub fn set_titlebar_separator_style(&self, style: crate::foundation::NSInteger) { pub fn set_titlebar_separator_style(&self, style: crate::foundation::NSInteger) {
unsafe { unsafe {
let _: () = msg_send![&*self.objc, setTitlebarSeparatorStyle:style]; let _: () = msg_send![&*self.objc, setTitlebarSeparatorStyle: style];
} }
} }
@ -513,7 +500,7 @@ impl<T> Drop for Window<T> {
unsafe { unsafe {
// Break the delegate - this shouldn't be an issue, but we should strive to be safe // Break the delegate - this shouldn't be an issue, but we should strive to be safe
// here anyway. // here anyway.
let _: () = msg_send![&*self.objc, setDelegate:nil]; let _: () = msg_send![&*self.objc, setDelegate: nil];
} }
} }
} }

View file

@ -28,7 +28,9 @@ pub trait WindowDelegate {
/// Called when the user has attempted to close the window. NOT called when a user quits the /// Called when the user has attempted to close the window. NOT called when a user quits the
/// application. Return false here if you need to handle the edge case. /// application. Return false here if you need to handle the edge case.
fn should_close(&self) -> bool { true } fn should_close(&self) -> bool {
true
}
/// Fires when a window is going to close. You might opt to, say, clean up things here - /// Fires when a window is going to close. You might opt to, say, clean up things here -
/// perhaps you have a long running task, or something that should be removed. /// perhaps you have a long running task, or something that should be removed.
@ -46,7 +48,9 @@ pub trait WindowDelegate {
/// ///
/// The default implementation of this method returns `None`, indicating the system should just /// The default implementation of this method returns `None`, indicating the system should just
/// do its thing. If you implement it, you probably want that. /// do its thing. If you implement it, you probably want that.
fn will_resize(&self, width: f64, height: f64) -> (f64, f64) { (width, height) } fn will_resize(&self, width: f64, height: f64) -> (f64, f64) {
(width, height)
}
/// Fired after the window has resized. /// Fired after the window has resized.
fn did_resize(&self) {} fn did_resize(&self) {}
@ -100,7 +104,9 @@ pub trait WindowDelegate {
/// Specify options for when this window goes full screen. /// Specify options for when this window goes full screen.
/// By default, this returns `None`, which tells the system to proceed as it normally would /// By default, this returns `None`, which tells the system to proceed as it normally would
/// without customization. /// without customization.
fn presentation_options_for_full_screen(&self) -> Option<&[PresentationOption]> { None } fn presentation_options_for_full_screen(&self) -> Option<&[PresentationOption]> {
None
}
/// Fires when this window is about to go full screen. /// Fires when this window is about to go full screen.
fn will_enter_full_screen(&self) {} fn will_enter_full_screen(&self) {}

View file

@ -49,15 +49,15 @@ macro_rules! method_decl_impl {
} }
); );
($($t:ident),*) => ( ($($t:ident),*) => (
method_decl_impl!(-T, R, extern fn(&T, Sel $(, $t)*) -> R, $($t),*); method_decl_impl!(-T, R, extern "C" fn(&T, Sel $(, $t)*) -> R, $($t),*);
method_decl_impl!(-T, R, extern fn(&mut T, Sel $(, $t)*) -> R, $($t),*); method_decl_impl!(-T, R, extern "C" fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
); );
} }
method_decl_impl!(); method_decl_impl!();
method_decl_impl!(A); method_decl_impl!(A);
extern fn get_bundle_id(this: &Object, s: Sel, v: id) -> id { extern "C" fn get_bundle_id(this: &Object, s: Sel, v: id) -> id {
unsafe { unsafe {
let bundle = class!(NSBundle); let bundle = class!(NSBundle);
let main_bundle: id = msg_send![bundle, mainBundle]; let main_bundle: id = msg_send![bundle, mainBundle];
@ -95,6 +95,6 @@ unsafe fn swizzle_bundle_id<F>(bundle_id: &str, func: F) where F: MethodImplemen
pub fn set_bundle_id(bundle_id: &str) { pub fn set_bundle_id(bundle_id: &str) {
unsafe { unsafe {
swizzle_bundle_id(bundle_id, get_bundle_id as extern fn(&Object, _, _) -> id); swizzle_bundle_id(bundle_id, get_bundle_id as extern "C" fn(&Object, _, _) -> id);
} }
} }

View file

@ -23,15 +23,15 @@ use std::sync::Once;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use objc_id::ShareId;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
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, sel_impl};
use objc_id::ShareId;
use crate::color::Color; use crate::color::Color;
use crate::control::Control; use crate::control::Control;
use crate::foundation::{id, nil, NSString, NSUInteger, BOOL, NO, YES};
use crate::image::Image; use crate::image::Image;
use crate::foundation::{id, nil, BOOL, YES, NO, NSString, NSUInteger};
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::keys::Key; use crate::keys::Key;
use crate::layout::Layout; use crate::layout::Layout;
@ -40,7 +40,7 @@ use crate::text::{AttributedString, Font};
use crate::utils::{load, properties::ObjcProperty}; use crate::utils::{load, properties::ObjcProperty};
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
use crate::appkit::FocusRingType; use crate::appkit::FocusRingType;
@ -129,10 +129,10 @@ impl Button {
action:nil action:nil
]; ];
let _: () = msg_send![button, setWantsLayer:YES]; let _: () = msg_send![button, setWantsLayer: YES];
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![button, setTranslatesAutoresizingMaskIntoConstraints: NO];
button button
}; };
@ -171,7 +171,7 @@ impl Button {
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view)
} }
} }
@ -190,7 +190,7 @@ impl Button {
let style: NSUInteger = bezel_style.into(); let style: NSUInteger = bezel_style.into();
self.objc.with_mut(|obj| unsafe { self.objc.with_mut(|obj| unsafe {
let _: () = msg_send![obj, setBezelStyle:style]; let _: () = msg_send![obj, setBezelStyle: style];
}); });
} }
@ -210,7 +210,7 @@ impl Button {
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
self.objc.with_mut(|obj| unsafe { self.objc.with_mut(|obj| unsafe {
let cell: id = msg_send![obj, cell]; let cell: id = msg_send![obj, cell];
let _: () = msg_send![cell, setBackgroundColor:color]; let _: () = msg_send![cell, setBackgroundColor: color];
}); });
} }
@ -279,7 +279,7 @@ impl Button {
let ring_type: NSUInteger = focus_ring_type.into(); let ring_type: NSUInteger = focus_ring_type.into();
self.objc.with_mut(|obj| unsafe { self.objc.with_mut(|obj| unsafe {
let _: () = msg_send![obj, setFocusRingType:ring_type]; let _: () = msg_send![obj, setFocusRingType: ring_type];
}); });
} }
@ -326,8 +326,8 @@ impl Drop for Button {
// but I'd rather be paranoid and remove them later. // but I'd rather be paranoid and remove them later.
fn drop(&mut self) { fn drop(&mut self) {
self.objc.with_mut(|obj| unsafe { self.objc.with_mut(|obj| unsafe {
let _: () = msg_send![obj, setTarget:nil]; let _: () = msg_send![obj, setTarget: nil];
let _: () = msg_send![obj, setAction:nil]; let _: () = msg_send![obj, setAction: nil];
}); });
} }
} }

View file

@ -19,7 +19,7 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO, NSInteger, NSUInteger, NSString, NSArray}; use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES};
use crate::utils::os; use crate::utils::os;
pub(crate) const AQUA_LIGHT_COLOR_NORMAL_CONTRAST: &'static str = "AQUA_LIGHT_COLOR_NORMAL_CONTRAST"; pub(crate) const AQUA_LIGHT_COLOR_NORMAL_CONTRAST: &'static str = "AQUA_LIGHT_COLOR_NORMAL_CONTRAST";
@ -82,164 +82,180 @@ fn get_effective_color(this: &Object) -> id {
} }
} }
extern fn color_space(this: &Object, _: Sel) -> id { extern "C" fn color_space(this: &Object, _: Sel) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorSpace] } unsafe { msg_send![color, colorSpace] }
} }
extern fn color_using_color_space(this: &Object, _: Sel, color_space: id) -> id { extern "C" fn color_using_color_space(this: &Object, _: Sel, color_space: id) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorUsingColorSpace:color_space] } unsafe { msg_send![color, colorUsingColorSpace: color_space] }
} }
extern fn color_space_name(this: &Object, _: Sel) -> id { extern "C" fn color_space_name(this: &Object, _: Sel) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorSpaceName] } unsafe { msg_send![color, colorSpaceName] }
} }
extern fn color_using_color_space_name(this: &Object, _: Sel, color_space_name: id) -> id { extern "C" fn color_using_color_space_name(this: &Object, _: Sel, color_space_name: id) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorUsingColorSpaceName:color_space_name] } unsafe { msg_send![color, colorUsingColorSpaceName: color_space_name] }
} }
extern fn number_of_components(this: &Object, _: Sel) -> NSInteger { extern "C" fn number_of_components(this: &Object, _: Sel) -> NSInteger {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, numberOfComponents] } unsafe { msg_send![color, numberOfComponents] }
} }
// @TODO: Confirm this. // @TODO: Confirm this.
extern fn get_components(this: &Object, _: Sel, components: CGFloat) { extern "C" fn get_components(this: &Object, _: Sel, components: CGFloat) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, getComponents:components]; } unsafe {
let _: () = msg_send![color, getComponents: components];
}
} }
// @TODO: Confirm this. // @TODO: Confirm this.
extern fn get_rgba(this: &Object, _: Sel, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { extern "C" fn get_rgba(this: &Object, _: Sel, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, getRed:red green:green blue:blue alpha:alpha]; } unsafe {
let _: () = msg_send![color, getRed:red green:green blue:blue alpha:alpha];
}
} }
extern fn red_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn red_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, redComponent] } unsafe { msg_send![color, redComponent] }
} }
extern fn green_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn green_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, greenComponent] } unsafe { msg_send![color, greenComponent] }
} }
extern fn blue_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn blue_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, blueComponent] } unsafe { msg_send![color, blueComponent] }
} }
extern fn hue_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn hue_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, hueComponent] } unsafe { msg_send![color, hueComponent] }
} }
extern fn saturation_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn saturation_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, saturationComponent] } unsafe { msg_send![color, saturationComponent] }
} }
extern fn brightness_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn brightness_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, brightnessComponent] } unsafe { msg_send![color, brightnessComponent] }
} }
// @TODO: Confirm this. // @TODO: Confirm this.
extern fn get_hsba(this: &Object, _: Sel, hue: CGFloat, sat: CGFloat, brit: CGFloat, alpha: CGFloat) { extern "C" fn get_hsba(this: &Object, _: Sel, hue: CGFloat, sat: CGFloat, brit: CGFloat, alpha: CGFloat) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, getHue:hue saturation:sat brightness:brit alpha:alpha]; } unsafe {
let _: () = msg_send![color, getHue:hue saturation:sat brightness:brit alpha:alpha];
}
} }
extern fn white_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn white_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, whiteComponent] } unsafe { msg_send![color, whiteComponent] }
} }
// @TODO: Confirm this. // @TODO: Confirm this.
extern fn get_white(this: &Object, _: Sel, white: CGFloat, alpha: CGFloat) { extern "C" fn get_white(this: &Object, _: Sel, white: CGFloat, alpha: CGFloat) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, getWhite:white alpha:alpha]; } unsafe {
let _: () = msg_send![color, getWhite:white alpha:alpha];
}
} }
extern fn cyan_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn cyan_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, cyanComponent] } unsafe { msg_send![color, cyanComponent] }
} }
extern fn magenta_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn magenta_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, magentaComponent] } unsafe { msg_send![color, magentaComponent] }
} }
extern fn yellow_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn yellow_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, yellowComponent] } unsafe { msg_send![color, yellowComponent] }
} }
extern fn black_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn black_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, blackComponent] } unsafe { msg_send![color, blackComponent] }
} }
// @TODO: Confirm this. // @TODO: Confirm this.
extern fn get_cmyk(this: &Object, _: Sel, c: CGFloat, m: CGFloat, y: CGFloat, k: CGFloat, a: CGFloat) { extern "C" fn get_cmyk(this: &Object, _: Sel, c: CGFloat, m: CGFloat, y: CGFloat, k: CGFloat, a: CGFloat) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, getCyan:c magenta:m yellow:y black:k alpha:a]; } unsafe {
let _: () = msg_send![color, getCyan:c magenta:m yellow:y black:k alpha:a];
}
} }
extern fn alpha_component(this: &Object, _: Sel) -> CGFloat { extern "C" fn alpha_component(this: &Object, _: Sel) -> CGFloat {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, alphaComponent] } unsafe { msg_send![color, alphaComponent] }
} }
extern fn cg_color(this: &Object, _: Sel) -> id { extern "C" fn cg_color(this: &Object, _: Sel) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, CGColor] } unsafe { msg_send![color, CGColor] }
} }
extern fn set_stroke(this: &Object, _: Sel) { extern "C" fn set_stroke(this: &Object, _: Sel) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, setStroke]; } unsafe {
let _: () = msg_send![color, setStroke];
}
} }
extern fn set_fill(this: &Object, _: Sel) { extern "C" fn set_fill(this: &Object, _: Sel) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, setFill]; } unsafe {
let _: () = msg_send![color, setFill];
}
} }
extern fn call_set(this: &Object, _: Sel) { extern "C" fn call_set(this: &Object, _: Sel) {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { let _: () = msg_send![color, set]; } unsafe {
let _: () = msg_send![color, set];
}
} }
extern fn highlight_with_level(this: &Object, _: Sel, level: CGFloat) -> id { extern "C" fn highlight_with_level(this: &Object, _: Sel, level: CGFloat) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, highlightWithLevel:level] } unsafe { msg_send![color, highlightWithLevel: level] }
} }
extern fn shadow_with_level(this: &Object, _: Sel, level: CGFloat) -> id { extern "C" fn shadow_with_level(this: &Object, _: Sel, level: CGFloat) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, shadowWithLevel:level] } unsafe { msg_send![color, shadowWithLevel: level] }
} }
extern fn color_with_alpha_component(this: &Object, _: Sel, alpha: CGFloat) -> id { extern "C" fn color_with_alpha_component(this: &Object, _: Sel, alpha: CGFloat) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorWithAlphaComponent:alpha] } unsafe { msg_send![color, colorWithAlphaComponent: alpha] }
} }
extern fn blended_color(this: &Object, _: Sel, fraction: CGFloat, with_color: id) -> id { extern "C" fn blended_color(this: &Object, _: Sel, fraction: CGFloat, with_color: id) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, blendedColorWithFraction:fraction ofColor:with_color] } unsafe { msg_send![color, blendedColorWithFraction:fraction ofColor:with_color] }
} }
extern fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger) -> id { extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger) -> id {
let color = get_effective_color(this); let color = get_effective_color(this);
unsafe { msg_send![color, colorWithSystemEffect:effect] } unsafe { msg_send![color, colorWithSystemEffect: effect] }
} }
pub(crate) fn register_class() -> *const Class { pub(crate) fn register_class() -> *const Class {
@ -251,45 +267,93 @@ pub(crate) fn register_class() -> *const Class {
let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap(); let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap();
// 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 fn(&Object, _) -> id); decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id);
decl.add_method(sel!(colorUsingColorSpace:), color_using_color_space as extern fn(&Object, _, id) -> id); decl.add_method(
decl.add_method(sel!(colorSpaceName), color_space_name as extern fn(&Object, _) -> id); sel!(colorUsingColorSpace:),
decl.add_method(sel!(colorUsingColorSpaceName:), color_using_color_space_name as extern fn(&Object, _, id) -> id); color_using_color_space as extern "C" fn(&Object, _, id) -> id
decl.add_method(sel!(numberOfComponents), number_of_components as extern fn(&Object, _) -> NSInteger); );
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 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 fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)); decl.add_method(
decl.add_method(sel!(redComponent), red_component as extern fn(&Object, _) -> CGFloat); sel!(getRed:green:blue:alpha:),
decl.add_method(sel!(greenComponent), green_component as extern fn(&Object, _) -> CGFloat); get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)
decl.add_method(sel!(blueComponent), blue_component as extern fn(&Object, _) -> 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 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 fn(&Object, _) -> CGFloat); decl.add_method(
decl.add_method(sel!(brightnessComponent), brightness_component as extern fn(&Object, _) -> CGFloat); sel!(saturationComponent),
decl.add_method(sel!(getHue:saturation:brightness:alpha:), get_hsba as extern fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat)); 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 fn(&Object, _) -> CGFloat); decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method(sel!(getWhite:alpha:), get_white as extern fn(&Object, _, CGFloat, 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 fn(&Object, _) -> CGFloat); decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method(sel!(magentaComponent), magenta_component as extern fn(&Object, _) -> CGFloat); decl.add_method(
decl.add_method(sel!(yellowComponent), yellow_component as extern fn(&Object, _) -> CGFloat); sel!(magentaComponent),
decl.add_method(sel!(blackComponent), black_component as extern fn(&Object, _) -> CGFloat); magenta_component as extern "C" fn(&Object, _) -> CGFloat
decl.add_method(sel!(getCyan:magenta:yellow:black:alpha:), get_cmyk as extern fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, 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 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 fn(&Object, _) -> id); decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id);
decl.add_method(sel!(setStroke), set_stroke as extern fn(&Object, _)); decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _));
decl.add_method(sel!(setFill), set_fill as extern fn(&Object, _)); decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _));
decl.add_method(sel!(set), call_set as extern fn(&Object, _)); decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _));
decl.add_method(sel!(highlightWithLevel:), highlight_with_level as extern fn(&Object, _, CGFloat) -> id); decl.add_method(
decl.add_method(sel!(shadowWithLevel:), shadow_with_level as extern fn(&Object, _, CGFloat) -> id); 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 fn(&Object, _, CGFloat) -> id); decl.add_method(
decl.add_method(sel!(blendedColorWithFraction:ofColor:), blended_color as extern fn(&Object, _, CGFloat, id) -> id); sel!(colorWithAlphaComponent:),
decl.add_method(sel!(colorWithSystemEffect:), color_with_system_effect as extern fn(&Object, _, NSInteger) -> id); 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_NORMAL_CONTRAST);
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST); decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST);

View file

@ -13,14 +13,13 @@
/// fallbacks, specify the `color_fallbacks` target_os in your `Cargo.toml`. /// fallbacks, specify the `color_fallbacks` target_os in your `Cargo.toml`.
/// ///
/// @TODO: bundle iOS/tvOS support. /// @TODO: bundle iOS/tvOS support.
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use core_graphics::color::CGColor; use core_graphics::color::CGColor;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::id; use crate::foundation::id;
@ -31,8 +30,8 @@ mod appkit_dynamic_color;
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
use appkit_dynamic_color::{ use appkit_dynamic_color::{
AQUA_LIGHT_COLOR_NORMAL_CONTRAST, AQUA_LIGHT_COLOR_HIGH_CONTRAST, AQUA_DARK_COLOR_HIGH_CONTRAST, AQUA_DARK_COLOR_NORMAL_CONTRAST, AQUA_LIGHT_COLOR_HIGH_CONTRAST,
AQUA_DARK_COLOR_NORMAL_CONTRAST, AQUA_DARK_COLOR_HIGH_CONTRAST AQUA_LIGHT_COLOR_NORMAL_CONTRAST
}; };
/// Represents a rendering style - dark mode or light mode. /// Represents a rendering style - dark mode or light mode.
@ -250,10 +249,14 @@ 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), colorWithCalibratedRed:r green:g blue:b alpha:a]) } {
Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedRed:r green:g blue:b alpha:a])
}
#[cfg(feature = "uikit")] #[cfg(feature = "uikit")]
{ Id::from_ptr(msg_send![class!(UIColor), colorWithRed:r green:g blue:b alpha:a]) } {
Id::from_ptr(msg_send![class!(UIColor), colorWithRed:r green:g blue:b alpha:a])
}
}))) })))
} }
@ -273,10 +276,14 @@ 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]) } {
Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedHue:h saturation:s brightness:b alpha:a])
}
#[cfg(feature = "uikit")] #[cfg(feature = "uikit")]
{ Id::from_ptr(msg_send![class!(UIColor), colorWithHue:h saturation:s brightness:b alpha:a]) } {
Id::from_ptr(msg_send![class!(UIColor), colorWithHue:h saturation:s brightness:b alpha:a])
}
}))) })))
} }
@ -291,10 +298,14 @@ impl Color {
pub fn white_alpha(level: CGFloat, alpha: CGFloat) -> Self { pub fn white_alpha(level: CGFloat, alpha: CGFloat) -> Self {
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]) } {
Id::from_ptr(msg_send![class!(NSColor), colorWithCalibratedWhite:level alpha:alpha])
}
#[cfg(feature = "uikit")] #[cfg(feature = "uikit")]
{ Id::from_ptr(msg_send![class!(UIColor), colorWithWhite:level alpha:alpha]) } {
Id::from_ptr(msg_send![class!(UIColor), colorWithWhite:level alpha:alpha])
}
}))) })))
} }
@ -346,7 +357,8 @@ impl Color {
let color: id = handler(Style { let color: id = handler(Style {
theme: Theme::Light, theme: Theme::Light,
contrast: Contrast::Normal contrast: Contrast::Normal
}).into(); })
.into();
color color
}); });
@ -355,7 +367,8 @@ impl Color {
let color: id = handler(Style { let color: id = handler(Style {
theme: Theme::Light, theme: Theme::Light,
contrast: Contrast::High contrast: Contrast::High
}).into(); })
.into();
color color
}); });
@ -364,7 +377,8 @@ impl Color {
let color: id = handler(Style { let color: id = handler(Style {
theme: Theme::Dark, theme: Theme::Dark,
contrast: Contrast::Normal contrast: Contrast::Normal
}).into(); })
.into();
color color
}); });
@ -373,7 +387,8 @@ impl Color {
let color: id = handler(Style { let color: id = handler(Style {
theme: Theme::Light, theme: Theme::Light,
contrast: Contrast::Normal contrast: Contrast::Normal
}).into(); })
.into();
color color
}); });
@ -421,7 +436,7 @@ impl From<&Color> for id {
/// Handles color fallback for system-provided colors. /// Handles color fallback for system-provided colors.
macro_rules! system_color_with_fallback { macro_rules! system_color_with_fallback {
($class:ident, $color:ident, $fallback:ident) => ({ ($class:ident, $color:ident, $fallback:ident) => {{
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
{ {
#[cfg(feature = "color-fallbacks")] #[cfg(feature = "color-fallbacks")]
@ -439,7 +454,7 @@ macro_rules! system_color_with_fallback {
{ {
msg_send![$class, $color] msg_send![$class, $color]
} }
}) }};
} }
/// This function maps enum types to system-provided colors, or our stored NS/UIColor objects. /// This function maps enum types to system-provided colors, or our stored NS/UIColor objects.
@ -508,6 +523,6 @@ unsafe fn to_objc(obj: &Color) -> id {
Color::MacOSWindowBackgroundColor => system_color_with_fallback!(color, windowBackgroundColor, clearColor), Color::MacOSWindowBackgroundColor => system_color_with_fallback!(color, windowBackgroundColor, clearColor),
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
Color::MacOSUnderPageBackgroundColor => system_color_with_fallback!(color, underPageBackgroundColor, clearColor), Color::MacOSUnderPageBackgroundColor => system_color_with_fallback!(color, underPageBackgroundColor, clearColor)
} }
} }

View file

@ -1,8 +1,7 @@
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, YES, NO, NSUInteger}; use crate::foundation::{id, NSUInteger, NO, YES};
use crate::objc_access::ObjcAccess; use crate::objc_access::ObjcAccess;
/// Use this enum for specifying NSControl size types. /// Use this enum for specifying NSControl size types.
@ -50,7 +49,7 @@ pub trait Control: ObjcAccess {
}; };
self.with_backing_obj_mut(|obj| unsafe { self.with_backing_obj_mut(|obj| unsafe {
let _: () = msg_send![obj, setControlSize:control_size]; let _: () = msg_send![obj, setControlSize: control_size];
}); });
} }
} }

View file

@ -33,14 +33,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{ use crate::foundation::{id, nil, to_bool, NSData, NSMutableDictionary, NSNumber, NSString, BOOL, NO, YES};
id, nil, to_bool, YES, NO, BOOL,
NSData, NSString, NSMutableDictionary, NSNumber
};
mod value; mod value;
pub use value::Value; pub use value::Value;
@ -73,9 +70,7 @@ impl UserDefaults {
/// let _ = defaults.get("test"); /// let _ = defaults.get("test");
/// ``` /// ```
pub fn standard() -> Self { pub fn standard() -> Self {
UserDefaults(unsafe { UserDefaults(unsafe { Id::from_ptr(msg_send![class!(NSUserDefaults), standardUserDefaults]) })
Id::from_ptr(msg_send![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
@ -177,9 +172,7 @@ impl UserDefaults {
pub fn get<K: AsRef<str>>(&self, key: K) -> Option<Value> { pub fn get<K: AsRef<str>>(&self, key: K) -> Option<Value> {
let key = NSString::new(key.as_ref()); let key = NSString::new(key.as_ref());
let result: id = unsafe { let result: id = unsafe { msg_send![&*self.0, objectForKey:&*key] };
msg_send![&*self.0, objectForKey:&*key]
};
if result == nil { if result == nil {
return None; return None;

View file

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::foundation::{id, NSData, NSMutableDictionary, NSString, NSNumber}; 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`.
/// ///

View file

@ -31,9 +31,7 @@ pub enum DragOperation {
Move, Move,
/// The data can be deleted. /// The data can be deleted.
Delete, Delete // All of the above.
// All of the above.
// @TODO: NSUIntegerMax, a tricky beast // @TODO: NSUIntegerMax, a tricky beast
// Every // Every
} }
@ -65,8 +63,6 @@ impl DragInfo {
/// ///
/// Note: in general, you should not store pasteboards. /// Note: in general, you should not store pasteboards.
pub fn get_pasteboard(&self) -> Pasteboard { pub fn get_pasteboard(&self) -> Pasteboard {
unsafe { unsafe { Pasteboard::with(msg_send![&*self.info, draggingPasteboard]) }
Pasteboard::with(msg_send![&*self.info, draggingPasteboard])
}
} }
} }

View file

@ -45,7 +45,9 @@ impl From<NSInteger> for ModalResponse {
// @TODO: Definitely don't panic here, wtf was I thinking? // @TODO: Definitely don't panic here, wtf was I thinking?
// Probably make this a ModalResponse::Unknown or something so a user can // Probably make this a ModalResponse::Unknown or something so a user can
// gracefully handle. // gracefully handle.
e => { panic!("Unknown NSModalResponse sent back! {}", e); } e => {
panic!("Unknown NSModalResponse sent back! {}", e);
}
} }
} }
} }

View file

@ -4,14 +4,14 @@
use std::error::Error; use std::error::Error;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use objc_id::Id; use objc::runtime::{Object, BOOL};
use objc::runtime::{BOOL, Object};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use url::Url; use url::Url;
use crate::foundation::{id, nil, NO, NSString, NSUInteger};
use crate::error::Error as AppKitError; use crate::error::Error as AppKitError;
use crate::filesystem::enums::{SearchPathDirectory, SearchPathDomainMask}; use crate::filesystem::enums::{SearchPathDirectory, SearchPathDomainMask};
use crate::foundation::{id, nil, NSString, NSUInteger, NO};
/// A FileManager can be used for file operations (moving files, etc). /// A FileManager can be used for file operations (moving files, etc).
/// ///
@ -45,11 +45,7 @@ impl FileManager {
/// 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.
/// Returns a PathBuf that wraps the given location. If there's an error on the Objective-C /// Returns a PathBuf that wraps the given location. If there's an error on the Objective-C
/// side, we attempt to catch it and bubble it up. /// side, we attempt to catch it and bubble it up.
pub fn get_directory( pub fn get_directory(&self, directory: SearchPathDirectory, in_domain: SearchPathDomainMask) -> Result<Url, Box<dyn Error>> {
&self,
directory: SearchPathDirectory,
in_domain: SearchPathDomainMask
) -> Result<Url, Box<dyn Error>> {
let dir: NSUInteger = directory.into(); let dir: NSUInteger = directory.into();
let mask: NSUInteger = in_domain.into(); let mask: NSUInteger = in_domain.into();

View file

@ -1,4 +1,3 @@
pub mod enums; pub mod enums;
pub use enums::*; pub use enums::*;

View file

@ -4,11 +4,11 @@
use block::ConcreteBlock; use block::ConcreteBlock;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSInteger, NSString}; use crate::foundation::{id, nil, NSInteger, NSString, NO, YES};
#[derive(Debug)] #[derive(Debug)]
pub struct FileSavePanel { pub struct FileSavePanel {
@ -39,9 +39,7 @@ impl FileSavePanel {
ShareId::from_ptr(x) ShareId::from_ptr(x)
}, },
delegate: unsafe { delegate: unsafe { ShareId::from_ptr(msg_send![class!(NSObject), new]) },
ShareId::from_ptr(msg_send![class!(NSObject), new])
},
can_create_directories: true can_create_directories: true
} }

View file

@ -6,12 +6,12 @@ use std::path::PathBuf;
use block::ConcreteBlock; use block::ConcreteBlock;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSInteger, NSString, NSURL};
use crate::filesystem::enums::ModalResponse; use crate::filesystem::enums::ModalResponse;
use crate::foundation::{id, nil, NSInteger, NSString, NO, NSURL, YES};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
use crate::appkit::window::{Window, WindowDelegate}; use crate::appkit::window::{Window, WindowDelegate};
@ -58,9 +58,7 @@ impl FileSelectPanel {
ShareId::from_ptr(x) ShareId::from_ptr(x)
}, },
delegate: unsafe { delegate: unsafe { ShareId::from_ptr(msg_send![class!(NSObject), new]) },
ShareId::from_ptr(msg_send![class!(NSObject), new])
},
can_choose_files: true, can_choose_files: true,
can_choose_directories: false, can_choose_directories: false,
@ -202,8 +200,8 @@ fn get_urls(panel: &Object) -> Vec<NSURL> {
let urls: id = msg_send![&*panel, URLs]; let urls: id = msg_send![&*panel, URLs];
let count: usize = msg_send![urls, count]; let count: usize = msg_send![urls, count];
(0..count).map(|index| { (0..count)
NSURL::retain(msg_send![urls, objectAtIndex:index]) .map(|index| NSURL::retain(msg_send![urls, objectAtIndex: index]))
}).collect() .collect()
} }
} }

View file

@ -16,12 +16,12 @@ pub trait OpenSaveController {
fn will_expand(&self, _expanding: bool) {} fn will_expand(&self, _expanding: bool) {}
/// Determine whether the specified URL should be enabled in the Open panel. /// Determine whether the specified URL should be enabled in the Open panel.
fn should_enable_url(&self, _url: &str) -> bool { true } fn should_enable_url(&self, _url: &str) -> bool {
true
}
} }
/// A trait you can implement for working with the underlying filesystem. This is important, /// A trait you can implement for working with the underlying filesystem. This is important,
/// notably, because sandboxed applications have different working restrictions surrounding what /// notably, because sandboxed applications have different working restrictions surrounding what
/// they can access. /// they can access.
pub trait FileManagerController { pub trait FileManagerController {}
}

View file

@ -1,7 +1,7 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::id; use crate::foundation::id;
@ -27,17 +27,13 @@ impl NSArray {
/// 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 { NSArray(unsafe { Id::from_ptr(array) })
Id::from_ptr(array)
})
} }
/// In some cases, we're vended an `NSArray` by the system, and it's ideal to not retain that. /// In some cases, we're vended an `NSArray` by the system, and it's ideal to not retain that.
/// This handles that edge case. /// This handles that edge case.
pub fn from_retained(array: id) -> Self { pub fn from_retained(array: id) -> Self {
NSArray(unsafe { NSArray(unsafe { Id::from_retained_ptr(array) })
Id::from_retained_ptr(array)
})
} }
/// Returns the `count` (`len()` equivalent) for the backing `NSArray`. /// Returns the `count` (`len()` equivalent) for the backing `NSArray`.
@ -54,10 +50,12 @@ impl NSArray {
// I don't know if it's worth trying to get in with NSFastEnumeration here. I'm content to // I don't know if it's worth trying to get in with NSFastEnumeration here. I'm content to
// just rely on Rust, but someone is free to profile it if they want. // just rely on Rust, but someone is free to profile it if they want.
(0..count).map(|index| { (0..count)
let item: id = unsafe { msg_send![objc, objectAtIndex:index] }; .map(|index| {
let item: id = unsafe { msg_send![objc, objectAtIndex: index] };
transform(item) transform(item)
}).collect() })
.collect()
} }
} }

View file

@ -1,5 +1,5 @@
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; 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,
@ -14,9 +14,7 @@ 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 { AutoReleasePool(unsafe { Id::from_retained_ptr(msg_send![class!(NSAutoreleasePool), new]) })
Id::from_retained_ptr(msg_send![class!(NSAutoreleasePool), new])
})
} }
/// Drains the underlying AutoreleasePool. /// Drains the underlying AutoreleasePool.

View file

@ -48,11 +48,7 @@ impl ClassMap {
} }
/// Attempts to load a previously registered subclass. /// Attempts to load a previously registered subclass.
pub fn load_subclass( pub fn load_subclass(&self, subclass_name: &'static str, superclass_name: &'static str) -> Option<*const Class> {
&self,
subclass_name: &'static str,
superclass_name: &'static str
) -> Option<*const Class> {
let reader = self.0.read().unwrap(); let reader = self.0.read().unwrap();
if let Some(inner) = (*reader).get(subclass_name) { if let Some(inner) = (*reader).get(subclass_name) {
@ -65,12 +61,7 @@ impl ClassMap {
} }
/// Store a newly created subclass type. /// Store a newly created subclass type.
pub fn store_subclass( pub fn store_subclass(&self, subclass_name: &'static str, superclass_name: &'static str, class: *const Class) {
&self,
subclass_name: &'static str,
superclass_name: &'static str,
class: *const Class,
) {
let mut writer = self.0.write().unwrap(); let mut writer = self.0.write().unwrap();
if let Some(map) = (*writer).get_mut(subclass_name) { if let Some(map) = (*writer).get_mut(subclass_name) {
@ -96,9 +87,7 @@ impl ClassMap {
} }
let objc_superclass_name = CString::new(name).unwrap(); let objc_superclass_name = CString::new(name).unwrap();
let superclass = unsafe { let superclass = unsafe { objc_getClass(objc_superclass_name.as_ptr() as *const _) };
objc_getClass(objc_superclass_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.
@ -131,11 +120,7 @@ impl ClassMap {
/// ///
/// There's definitely room to optimize here, but it works for now. /// There's definitely room to optimize here, but it works for now.
#[inline(always)] #[inline(always)]
pub fn load_or_register_class<F>( pub fn load_or_register_class<F>(superclass_name: &'static str, subclass_name: &'static str, config: F) -> *const Class
superclass_name: &'static str,
subclass_name: &'static str,
config: F
) -> *const Class
where where
F: Fn(&mut ClassDecl) + 'static F: Fn(&mut ClassDecl) + 'static
{ {
@ -158,8 +143,7 @@ where
None => { None => {
panic!( panic!(
"Subclass of type {}_{} could not be allocated.", "Subclass of type {}_{} could not be allocated.",
subclass_name, subclass_name, superclass_name
superclass_name
); );
} }
} }
@ -167,7 +151,6 @@ where
panic!( panic!(
"Attempted to create subclass for {}, but unable to load superclass of type {}.", "Attempted to create subclass for {}, but unable to load superclass of type {}.",
subclass_name, subclass_name, superclass_name
superclass_name
); );
} }

View file

@ -5,11 +5,11 @@ use std::slice;
use block::{Block, ConcreteBlock}; use block::{Block, ConcreteBlock};
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, to_bool, BOOL, YES, NO, NSUInteger}; use crate::foundation::{id, to_bool, NSUInteger, BOOL, NO, YES};
/// Wrapper for a retained `NSData` object. /// Wrapper for a retained `NSData` object.
/// ///
@ -67,24 +67,18 @@ impl NSData {
/// 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 { NSData(unsafe { Id::from_ptr(data) })
Id::from_ptr(data)
})
} }
/// If we're vended an NSData from a method (e.g, a push notification token) we might want to /// 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. /// wrap it while we figure out what to do with it. This does that.
pub fn from_retained(data: id) -> Self { pub fn from_retained(data: id) -> Self {
NSData(unsafe { NSData(unsafe { Id::from_retained_ptr(data) })
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`.
pub fn is(obj: id) -> bool { pub fn is(obj: id) -> bool {
let result: BOOL = unsafe { let result: BOOL = unsafe { msg_send![obj, isKindOfClass: class!(NSData)] };
msg_send![obj, isKindOfClass:class!(NSData)]
};
to_bool(result) to_bool(result)
} }
@ -112,9 +106,7 @@ impl NSData {
(ptr as *const u8, self.len()) (ptr as *const u8, self.len())
}; };
unsafe { unsafe { slice::from_raw_parts(ptr, len) }
slice::from_raw_parts(ptr, len)
}
} }
/// Creates a new Vec, copies the NSData (safely, but quickly) bytes into that Vec, and /// Creates a new Vec, copies the NSData (safely, but quickly) bytes into that Vec, and

View file

@ -1,8 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, NSString}; use crate::foundation::{id, NSString};
@ -26,9 +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 { NSMutableDictionary(unsafe { Id::from_ptr(msg_send![class!(NSMutableDictionary), new]) })
Id::from_ptr(msg_send![class!(NSMutableDictionary), new])
})
} }
/// Inserts an object into the backing NSMutablyDictionary. /// Inserts an object into the backing NSMutablyDictionary.

View file

@ -44,7 +44,7 @@ pub use string::NSString;
// Separate named module to not conflict with the `url` crate. Go figure. // Separate named module to not conflict with the `url` crate. Go figure.
mod urls; mod urls;
pub use urls::{NSURL, NSURLBookmarkCreationOption, NSURLBookmarkResolutionOption}; pub use urls::{NSURLBookmarkCreationOption, NSURLBookmarkResolutionOption, NSURL};
/// Bool mapping types differ between ARM and x64. There's a number of places that we need to check /// Bool mapping types differ between ARM and x64. There's a number of places that we need to check
/// against BOOL results throughout the framework, and this just simplifies some mismatches. /// against BOOL results throughout the framework, and this just simplifies some mismatches.
@ -56,7 +56,9 @@ pub fn to_bool(result: BOOL) -> bool {
//#[cfg(target_arch = "aarch64")] //#[cfg(target_arch = "aarch64")]
#[cfg(not(target_arch = "aarch64"))] #[cfg(not(target_arch = "aarch64"))]
_ => { std::unreachable!(); } _ => {
std::unreachable!();
}
} }
} }

View file

@ -1,11 +1,11 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char; use std::os::raw::c_char;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, to_bool, BOOL, YES, NO, NSInteger}; use crate::foundation::{id, to_bool, NSInteger, BOOL, NO, YES};
/// Wrapper for a `NSNumber` object. /// Wrapper for a `NSNumber` object.
/// ///
@ -18,17 +18,13 @@ 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 { NSNumber(unsafe { Id::from_ptr(data) })
Id::from_ptr(data)
})
} }
/// 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 it while we figure out what to do with it. This does that. /// wrap it while we figure out what to do with it. This does that.
pub fn wrap(data: id) -> Self { pub fn wrap(data: id) -> Self {
NSNumber(unsafe { NSNumber(unsafe { Id::from_retained_ptr(data) })
Id::from_retained_ptr(data)
})
} }
/// Constructs a `numberWithBool` instance of `NSNumber` and retains it. /// Constructs a `numberWithBool` instance of `NSNumber` and retains it.
@ -43,16 +39,12 @@ impl NSNumber {
/// 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 { NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithInteger: value as NSInteger]) })
Id::from_retained_ptr(msg_send![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 { NSNumber(unsafe { Id::from_retained_ptr(msg_send![class!(NSNumber), numberWithDouble: value]) })
Id::from_retained_ptr(msg_send![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
@ -84,9 +76,7 @@ impl NSNumber {
/// Note that this _does not check_ if the underlying type is actually this. You are /// Note that this _does not check_ if the underlying type is actually this. You are
/// responsible for doing so via the `objc_type()` method. /// responsible for doing so via the `objc_type()` method.
pub fn as_f64(&self) -> f64 { pub fn as_f64(&self) -> f64 {
unsafe { unsafe { msg_send![&*self.0, doubleValue] }
msg_send![&*self.0, doubleValue]
}
} }
/// Pulls the underlying `BOOL` value out and passes it back as a `bool`. /// Pulls the underlying `BOOL` value out and passes it back as a `bool`.
@ -94,18 +84,14 @@ impl NSNumber {
/// Note that this _does not check_ if the underlying type is actually this. You are /// Note that this _does not check_ if the underlying type is actually this. You are
/// responsible for doing so via the `objc_type()` method. /// responsible for doing so via the `objc_type()` method.
pub fn as_bool(&self) -> bool { pub fn as_bool(&self) -> bool {
let result: BOOL = unsafe { let result: BOOL = unsafe { msg_send![&*self.0, boolValue] };
msg_send![&*self.0, boolValue]
};
to_bool(result) to_bool(result)
} }
/// A helper method for determining if a given `NSObject` is an `NSNumber`. /// A helper method for determining if a given `NSObject` is an `NSNumber`.
pub fn is(obj: id) -> bool { pub fn is(obj: id) -> bool {
let result: BOOL = unsafe { let result: BOOL = unsafe { msg_send![obj, isKindOfClass: class!(NSNumber)] };
msg_send![obj, isKindOfClass:class!(NSNumber)]
};
to_bool(result) to_bool(result)
} }

View file

@ -1,13 +1,13 @@
use std::{fmt, slice, str};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::os::raw::c_char; use std::os::raw::c_char;
use std::{fmt, slice, str};
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, to_bool, BOOL, YES, NO}; use crate::foundation::{id, to_bool, BOOL, NO, YES};
const UTF8_ENCODING: usize = 4; const UTF8_ENCODING: usize = 4;
@ -73,7 +73,7 @@ impl<'a> NSString<'a> {
/// Utility method for checking whether an `NSObject` is an `NSString`. /// Utility method for checking whether an `NSObject` is an `NSString`.
pub fn is(obj: id) -> bool { pub fn is(obj: id) -> bool {
let result: BOOL = unsafe { msg_send![obj, isKindOfClass:class!(NSString)] }; let result: BOOL = unsafe { msg_send![obj, isKindOfClass: class!(NSString)] };
to_bool(result) to_bool(result)
} }
@ -87,9 +87,7 @@ impl<'a> NSString<'a> {
/// Helper method for grabbing the proper byte length for this `NSString` (the UTF8 variant). /// Helper method for grabbing the proper byte length for this `NSString` (the UTF8 variant).
fn bytes_len(&self) -> usize { fn bytes_len(&self) -> usize {
unsafe { unsafe { msg_send![&*self.objc, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
msg_send![&*self.objc, lengthOfBytesUsingEncoding:UTF8_ENCODING]
}
} }
/// A utility method for taking an `NSString` and bridging it to a Rust `&str`. /// A utility method for taking an `NSString` and bridging it to a Rust `&str`.

View file

@ -3,8 +3,8 @@ use std::marker::PhantomData;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::path::PathBuf; use std::path::PathBuf;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, NSData, NSString, NSUInteger}; use crate::foundation::{id, nil, NSData, NSString, NSUInteger};
@ -13,7 +13,7 @@ mod bookmark_options;
pub use bookmark_options::{NSURLBookmarkCreationOption, NSURLBookmarkResolutionOption}; pub use bookmark_options::{NSURLBookmarkCreationOption, NSURLBookmarkResolutionOption};
mod resource_keys; mod resource_keys;
pub use resource_keys::{NSURLResourceKey, NSURLFileResource, NSUbiquitousItemDownloadingStatus}; pub use resource_keys::{NSURLFileResource, NSURLResourceKey, NSUbiquitousItemDownloadingStatus};
/// Wraps `NSURL` for use throughout the framework. /// Wraps `NSURL` for use throughout the framework.
/// ///
@ -58,9 +58,7 @@ impl<'a> NSURL<'a> {
let url = NSString::new(url); let url = NSString::new(url);
Self { Self {
objc: unsafe { objc: unsafe { ShareId::from_ptr(msg_send![class!(NSURL), URLWithString:&*url]) },
ShareId::from_ptr(msg_send![class!(NSURL), URLWithString:&*url])
},
phantom: PhantomData phantom: PhantomData
} }
@ -71,9 +69,7 @@ impl<'a> NSURL<'a> {
/// Note that if the underlying file moved, this won't be accurate - you likely want to /// Note that if the underlying file moved, this won't be accurate - you likely want to
/// research URL bookmarks. /// research URL bookmarks.
pub fn absolute_string(&self) -> String { pub fn absolute_string(&self) -> String {
let abs_str = NSString::retain(unsafe { let abs_str = NSString::retain(unsafe { msg_send![&*self.objc, absoluteString] });
msg_send![&*self.objc, absoluteString]
});
abs_str.to_string() abs_str.to_string()
} }
@ -81,9 +77,7 @@ impl<'a> NSURL<'a> {
/// Creates and returns a Rust `PathBuf`, for users who don't need the extra pieces of NSURL /// Creates and returns a Rust `PathBuf`, for users who don't need the extra pieces of NSURL
/// and just want to write Rust code. /// and just want to write Rust code.
pub fn pathbuf(&self) -> PathBuf { pub fn pathbuf(&self) -> PathBuf {
let path = NSString::retain(unsafe { let path = NSString::retain(unsafe { msg_send![&*self.objc, path] });
msg_send![&*self.objc, path]
});
path.to_str().into() path.to_str().into()
} }

View file

@ -1,6 +1,6 @@
//! Wrapper methods for various geometry types (rects, sizes, ec). //! Wrapper methods for various geometry types (rects, sizes, ec).
use core_graphics::geometry::{CGRect, CGPoint, CGSize}; use core_graphics::geometry::{CGPoint, CGRect, CGSize};
/// A struct that represents a box - top, left, width and height. You might use this for, say, /// A struct that represents a box - top, left, width and height. You might use this for, say,
/// setting the initial frame of a view. /// setting the initial frame of a view.
@ -22,7 +22,12 @@ pub struct Rect {
impl Rect { impl Rect {
/// Returns a new `Rect` initialized with the values specified. /// Returns a new `Rect` initialized with the values specified.
pub fn new(top: f64, left: f64, width: f64, height: f64) -> Self { pub fn new(top: f64, left: f64, width: f64, height: f64) -> Self {
Rect { top: top, left: left, width: width, height: height } Rect {
top: top,
left: left,
width: width,
height: height
}
} }
/// Returns a zero'd out Rect, with f64 (32-bit is mostly dead on Cocoa, so... this is "okay"). /// Returns a zero'd out Rect, with f64 (32-bit is mostly dead on Cocoa, so... this is "okay").
@ -38,10 +43,7 @@ impl Rect {
impl From<Rect> for CGRect { impl From<Rect> for CGRect {
fn from(rect: Rect) -> CGRect { fn from(rect: Rect) -> CGRect {
CGRect::new( CGRect::new(&CGPoint::new(rect.left, rect.top), &CGSize::new(rect.width, rect.height))
&CGPoint::new(rect.left, rect.top),
&CGSize::new(rect.width, rect.height)
)
} }
} }

View file

@ -14,10 +14,10 @@ use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, YES, NO, NSUInteger};
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; use crate::foundation::{id, NSUInteger, NO, YES};
use crate::utils::load; use crate::utils::load;
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
@ -30,7 +30,7 @@ pub(crate) fn register_image_view_class() -> *const Class {
let superclass = class!(NSImageView); let superclass = class!(NSImageView);
let decl = ClassDecl::new("RSTImageView", superclass).unwrap(); let decl = ClassDecl::new("RSTImageView", superclass).unwrap();
//decl.add_method(sel!(isFlipped), enforce_normalcy as extern fn(&Object, _) -> BOOL); //decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });

View file

@ -1,19 +1,19 @@
use objc_id::ShareId;
use objc::runtime::Object; use objc::runtime::Object;
use objc_id::ShareId;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use block::ConcreteBlock; use block::ConcreteBlock;
use core_graphics::{
base::{CGFloat},
geometry::{CGRect, CGPoint, CGSize}
};
use core_graphics::context::{CGContext, CGContextRef}; use core_graphics::context::{CGContext, CGContextRef};
use core_graphics::{
base::CGFloat,
geometry::{CGPoint, CGRect, CGSize}
};
use crate::foundation::{id, YES, NO, NSString, NSData};
use crate::utils::os;
use super::icons::*; use super::icons::*;
use crate::foundation::{id, NSData, NSString, NO, YES};
use crate::utils::os;
/// Specifies resizing behavior for image drawing. /// Specifies resizing behavior for image drawing.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -32,7 +32,9 @@ pub enum ResizeBehavior {
} }
fn max_cgfloat(x: CGFloat, y: CGFloat) -> CGFloat { fn max_cgfloat(x: CGFloat, y: CGFloat) -> CGFloat {
if x == y { return x; } if x == y {
return x;
}
match x > y { match x > y {
true => x, true => x,
@ -41,7 +43,9 @@ fn max_cgfloat(x: CGFloat, y: CGFloat) -> CGFloat {
} }
fn min_cgfloat(x: CGFloat, y: CGFloat) -> CGFloat { fn min_cgfloat(x: CGFloat, y: CGFloat) -> CGFloat {
if x == y { return x; } if x == y {
return x;
}
match x < y { match x < y {
true => x, true => x,
@ -54,21 +58,15 @@ impl ResizeBehavior {
/// the resizing properties of this enum. /// the resizing properties of this enum.
pub fn apply(&self, source: CGRect, target: CGRect) -> CGRect { pub fn apply(&self, source: CGRect, target: CGRect) -> CGRect {
// if equal, just return source // if equal, just return source
if if source.origin.x == target.origin.x
source.origin.x == target.origin.x && && source.origin.y == target.origin.y
source.origin.y == target.origin.y && && source.size.width == target.size.width
source.size.width == target.size.width && && source.size.height == target.size.height
source.size.height == target.size.height
{ {
return source; return source;
} }
if if source.origin.x == 0. && source.origin.y == 0. && source.size.width == 0. && source.size.height == 0. {
source.origin.x == 0. &&
source.origin.y == 0. &&
source.size.width == 0. &&
source.size.height == 0.
{
return source; return source;
} }
@ -126,9 +124,7 @@ pub struct Image(pub ShareId<Object>);
impl Image { 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 { Image(unsafe { ShareId::from_ptr(image) })
ShareId::from_ptr(image)
})
} }
/// Loads an image from the specified path. /// Loads an image from the specified path.
@ -137,7 +133,7 @@ impl Image {
Image(unsafe { Image(unsafe {
let alloc: id = msg_send![class!(NSImage), alloc]; let alloc: id = msg_send![class!(NSImage), alloc];
ShareId::from_ptr(msg_send![alloc, initWithContentsOfFile:file_path]) ShareId::from_ptr(msg_send![alloc, initWithContentsOfFile: file_path])
}) })
} }
@ -148,7 +144,7 @@ impl Image {
Image(unsafe { Image(unsafe {
let alloc: id = msg_send![class!(NSImage), alloc]; let alloc: id = msg_send![class!(NSImage), alloc];
ShareId::from_ptr(msg_send![alloc, initWithData:data]) ShareId::from_ptr(msg_send![alloc, initWithData: data])
}) })
} }
@ -161,7 +157,7 @@ impl Image {
Image(unsafe { Image(unsafe {
ShareId::from_ptr({ ShareId::from_ptr({
let icon = icon.to_id(); let icon = icon.to_id();
msg_send![class!(NSImage), imageNamed:icon] msg_send![class!(NSImage), imageNamed: icon]
}) })
}) })
} }
@ -189,7 +185,7 @@ impl Image {
false => { false => {
let icon = icon.to_id(); let icon = icon.to_id();
msg_send![class!(NSImage), imageNamed:icon] msg_send![class!(NSImage), imageNamed: icon]
} }
}) })
}) })
@ -221,15 +217,9 @@ impl Image {
where where
F: Fn(CGRect, &CGContextRef) -> bool + 'static F: Fn(CGRect, &CGContextRef) -> bool + 'static
{ {
let source_frame = CGRect::new( let source_frame = CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(config.source.0, config.source.1));
&CGPoint::new(0., 0.),
&CGSize::new(config.source.0, config.source.1)
);
let target_frame = CGRect::new( let target_frame = CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(config.target.0, config.target.1));
&CGPoint::new(0., 0.),
&CGSize::new(config.target.0, config.target.1)
);
let resized_frame = config.resize.apply(source_frame, target_frame); let resized_frame = config.resize.apply(source_frame, target_frame);

View file

@ -1,15 +1,15 @@
use objc_id::ShareId;
use objc::runtime::{Class, Object}; use objc::runtime::{Class, Object};
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId;
use crate::foundation::{id, nil, YES, NO, NSArray, NSString};
use crate::color::Color; use crate::color::Color;
use crate::foundation::{id, nil, NSArray, NSString, NO, YES};
use crate::layout::Layout; use crate::layout::Layout;
use crate::objc_access::ObjcAccess; use crate::objc_access::ObjcAccess;
use crate::utils::properties::ObjcProperty; use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
mod appkit; mod appkit;
@ -24,7 +24,7 @@ use appkit::register_image_view_class;
//use uikit::register_image_view_class; //use uikit::register_image_view_class;
mod image; mod image;
pub use image::{Image, DrawConfig, ResizeBehavior}; pub use image::{DrawConfig, Image, ResizeBehavior};
mod icons; mod icons;
pub use icons::*; pub use icons::*;
@ -35,10 +35,10 @@ fn allocate_view(registration_fn: fn() -> *const Class) -> id {
let view: id = msg_send![registration_fn(), new]; let view: id = msg_send![registration_fn(), new];
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints:NO]; let _: () = msg_send![view, setTranslatesAutoresizingMaskIntoConstraints: NO];
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
let _: () = msg_send![view, setWantsLayer:YES]; let _: () = msg_send![view, setWantsLayer: YES];
view view
} }
@ -135,7 +135,7 @@ impl ImageView {
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(view), center_y: LayoutAnchorY::center(view),
objc: ObjcProperty::retain(view), objc: ObjcProperty::retain(view)
} }
} }
@ -144,7 +144,7 @@ impl ImageView {
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();
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];
}); });
} }

View file

@ -6,7 +6,7 @@ use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::foundation::{load_or_register_class, id, NSString, NSUInteger, NO, YES}; use crate::foundation::{id, load_or_register_class, NSString, NSUInteger, NO, YES};
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR}; use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
use crate::utils::load; use crate::utils::load;
@ -29,11 +29,7 @@ extern "C" fn text_did_change<T: TextFieldDelegate>(this: &mut Object, _: Sel, _
view.text_did_change(s.to_str()); view.text_did_change(s.to_str());
} }
extern "C" fn text_should_begin_editing<T: TextFieldDelegate>( extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
this: &mut 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] });
@ -43,11 +39,7 @@ extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(
} }
} }
extern "C" fn text_should_end_editing<T: TextFieldDelegate>( extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) -> BOOL {
this: &mut 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()) { match view.text_should_end_editing(s.to_str()) {
@ -82,23 +74,20 @@ pub(crate) fn register_view_class_with_delegate<T: TextFieldDelegate>(instance:
decl.add_method( decl.add_method(
sel!(textDidEndEditing:), sel!(textDidEndEditing:),
text_did_end_editing::<T> as extern "C" fn(&mut Object, _, _), 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(&mut Object, _, _)
);
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(&mut Object, _, _));
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(&mut Object, Sel, id) -> BOOL
); );
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(&mut Object, Sel, id) -> BOOL
); );
}) })
} }

View file

@ -135,7 +135,7 @@ pub struct TextField<T = ()> {
/// A pointer to the Objective-C runtime center Y layout constraint. /// A pointer to the Objective-C runtime center Y layout constraint.
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
pub center_y: LayoutAnchorY, pub center_y: LayoutAnchorY
} }
impl Default for TextField { impl Default for TextField {
@ -189,7 +189,7 @@ impl TextField {
impl<T> TextField<T> impl<T> TextField<T>
where where
T: TextFieldDelegate + 'static, T: TextFieldDelegate + 'static
{ {
/// Initializes a new TextField with a given `TextFieldDelegate`. This enables you to respond to events /// Initializes a new TextField with a given `TextFieldDelegate`. This enables you to respond to events
/// and customize the view as a module, similar to class-based systems. /// and customize the view as a module, similar to class-based systems.
@ -235,7 +235,7 @@ where
center_x: LayoutAnchorX::center(label), center_x: LayoutAnchorX::center(label),
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
center_y: LayoutAnchorY::center(label), center_y: LayoutAnchorY::center(label)
}; };
(&mut delegate).did_load(label.clone_as_handle()); (&mut delegate).did_load(label.clone_as_handle());
@ -282,15 +282,14 @@ impl<T> TextField<T> {
center_x: self.center_x.clone(), center_x: self.center_x.clone(),
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
center_y: self.center_y.clone(), center_y: self.center_y.clone()
} }
} }
/// Grabs the value from the textfield and returns it as an owned String. /// Grabs the value from the textfield and returns it as an owned String.
pub fn get_value(&self) -> String { pub fn get_value(&self) -> String {
self.objc.get(|obj| unsafe { self.objc
NSString::retain(msg_send![obj, stringValue]).to_string() .get(|obj| unsafe { NSString::retain(msg_send![obj, stringValue]).to_string() })
})
} }
/// Call this to set the background color for the backing layer. /// Call this to set the background color for the backing layer.
@ -353,7 +352,7 @@ impl<T> TextField<T> {
/// Sets the maximum number of lines. /// Sets the maximum number of lines.
pub fn set_max_number_of_lines(&self, num: NSInteger) { pub fn set_max_number_of_lines(&self, num: NSInteger) {
self.objc.with_mut(|obj| unsafe { self.objc.with_mut(|obj| unsafe {
let _: () = msg_send![obj, setMaximumNumberOfLines:num]; let _: () = msg_send![obj, setMaximumNumberOfLines: num];
}); });
} }

View file

@ -11,11 +11,11 @@
use std::fmt; use std::fmt;
use std::sync::{Arc, Mutex, Once}; use std::sync::{Arc, Mutex, Once};
use objc_id::ShareId; use block::{Block, ConcreteBlock, RcBlock};
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
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, sel_impl};
use block::{Block, ConcreteBlock, RcBlock}; use objc_id::ShareId;
use crate::foundation::{id, nil, NSString}; use crate::foundation::{id, nil, NSString};
use crate::utils::load; use crate::utils::load;
@ -34,8 +34,7 @@ pub struct Action(Box<dyn Fn() + Send + Sync + 'static>);
impl fmt::Debug for Action { impl fmt::Debug for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Action") f.debug_struct("Action").finish()
.finish()
} }
} }
@ -64,8 +63,8 @@ impl TargetActionHandler {
let invoker: id = msg_send![register_invoker_class::<F>(), alloc]; let invoker: id = msg_send![register_invoker_class::<F>(), alloc];
let invoker: id = msg_send![invoker, init]; let invoker: id = msg_send![invoker, init];
(&mut *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 invoker
}) })
}; };
@ -78,7 +77,7 @@ impl TargetActionHandler {
} }
/// This will fire for an NSButton callback. /// This will fire for an NSButton callback.
extern fn perform<F: Fn() + 'static>(this: &mut Object, _: Sel, _sender: id) { extern "C" fn perform<F: Fn() + 'static>(this: &mut Object, _: Sel, _sender: id) {
let action = load::<Action>(this, ACTION_CALLBACK_PTR); let action = load::<Action>(this, ACTION_CALLBACK_PTR);
(action.0)(); (action.0)();
} }
@ -104,7 +103,7 @@ pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class {
let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap(); let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap();
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR); decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
decl.add_method(sel!(perform:), perform::<F> as extern fn (&mut Object, _, id)); decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });

View file

@ -38,9 +38,7 @@ 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 { objc: ObjcProperty::retain(unsafe { msg_send![class!(CALayer), new] })
msg_send![class!(CALayer), new]
})
} }
} }
@ -56,7 +54,7 @@ impl Layer {
/// 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 { self.objc.with_mut(|obj| unsafe {
let _: () = msg_send![obj, setCornerRadius:radius as CGFloat]; let _: () = msg_send![obj, setCornerRadius: radius as CGFloat];
}); });
} }
} }

View file

@ -1,7 +1,7 @@
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use objc::{msg_send, sel, sel_impl};
use objc::runtime::{Class, Object}; use objc::runtime::{Class, Object};
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::id; use crate::foundation::id;
@ -13,15 +13,13 @@ pub struct LayoutConstraintAnimatorProxy(pub ShareId<Object>);
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 { Self(unsafe { ShareId::from_ptr(msg_send![proxy, animator]) })
ShareId::from_ptr(msg_send![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.
pub fn set_offset(&self, value: CGFloat) { pub fn set_offset(&self, value: CGFloat) {
unsafe { unsafe {
let _: () = msg_send![&*self.0, setConstant:value]; let _: () = msg_send![&*self.0, setConstant: value];
} }
} }
} }

View file

@ -4,11 +4,11 @@
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, YES, NO}; use crate::foundation::{id, NO, YES};
use super::LayoutConstraintAnimatorProxy; use super::LayoutConstraintAnimatorProxy;
@ -42,7 +42,7 @@ impl LayoutConstraint {
constraint: unsafe { ShareId::from_ptr(object) }, constraint: unsafe { ShareId::from_ptr(object) },
offset: 0.0, offset: 0.0,
multiplier: 0.0, multiplier: 0.0,
priority: 0.0, priority: 0.0
} }
} }
@ -51,10 +51,9 @@ impl LayoutConstraint {
let offset: f64 = offset.into(); let offset: f64 = offset.into();
unsafe { unsafe {
let o = offset as CGFloat; let o = offset as CGFloat;
let _: () = msg_send![&*self.constraint, setConstant:o]; let _: () = msg_send![&*self.constraint, setConstant: o];
} }
LayoutConstraint { LayoutConstraint {
animator: self.animator, animator: self.animator,
constraint: self.constraint, constraint: self.constraint,
@ -70,7 +69,7 @@ impl LayoutConstraint {
unsafe { unsafe {
let o = offset as CGFloat; let o = offset as CGFloat;
let _: () = msg_send![&*self.constraint, setConstant:o]; let _: () = msg_send![&*self.constraint, setConstant: o];
} }
} }
@ -96,23 +95,19 @@ impl LayoutConstraint {
// I regret nothing, lol. If you have a better solution I'm all ears. // I regret nothing, lol. If you have a better solution I'm all ears.
pub fn activate(constraints: &[LayoutConstraint]) { pub fn activate(constraints: &[LayoutConstraint]) {
unsafe { unsafe {
let ids: Vec<&Object> = constraints.into_iter().map(|constraint| { let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect();
&*constraint.constraint
}).collect();
let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()]; let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()];
let _: () = msg_send![class!(NSLayoutConstraint), activateConstraints:constraints]; let _: () = msg_send![class!(NSLayoutConstraint), activateConstraints: constraints];
} }
} }
pub fn deactivate(constraints: &[LayoutConstraint]) { pub fn deactivate(constraints: &[LayoutConstraint]) {
unsafe { unsafe {
let ids: Vec<&Object> = constraints.into_iter().map(|constraint| { let ids: Vec<&Object> = constraints.into_iter().map(|constraint| &*constraint.constraint).collect();
&*constraint.constraint
}).collect();
let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()]; let constraints: id = msg_send![class!(NSArray), arrayWithObjects:ids.as_ptr() count:ids.len()];
let _: () = msg_send![class!(NSLayoutConstraint), deactivateConstraints:constraints]; let _: () = msg_send![class!(NSLayoutConstraint), deactivateConstraints: constraints];
} }
} }
} }

View file

@ -1,7 +1,7 @@
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use objc::{class, msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, NSInteger}; use crate::foundation::{id, nil, NSInteger};
@ -38,16 +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 { Self::Width(unsafe { ShareId::from_ptr(msg_send![view, widthAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Height(unsafe { ShareId::from_ptr(msg_send![view, heightAnchor]) })
ShareId::from_ptr(msg_send![view, heightAnchor])
})
} }
/// Return a constraint equal to a constant value. /// Return a constraint equal to a constant value.
@ -55,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]
}); });
} }
@ -67,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]
}); });
} }
@ -79,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]
}); });
} }
@ -94,12 +90,10 @@ impl LayoutAnchorDimension {
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
{ {
match (self, anchor_to) { match (self, anchor_to) {
(Self::Width(from), Self::Width(to)) | (Self::Width(from), Self::Width(to))
(Self::Width(from), Self::Height(to)) | | (Self::Width(from), Self::Height(to))
(Self::Height(from), Self::Width(to)) | | (Self::Height(from), Self::Width(to))
(Self::Height(from), Self::Height(to)) => { | (Self::Height(from), Self::Height(to)) => LayoutConstraint::new(handler(from, to)),
LayoutConstraint::new(handler(from, to))
},
(Self::Uninitialized, Self::Uninitialized) => { (Self::Uninitialized, Self::Uninitialized) => {
panic!("Attempted to create constraints with an uninitialized \"from\" and \"to\" dimension anchor."); panic!("Attempted to create constraints with an uninitialized \"from\" and \"to\" dimension anchor.");
@ -109,7 +103,6 @@ impl LayoutAnchorDimension {
panic!("Attempted to create constraints with an uninitialized \"from\" dimension anchor."); panic!("Attempted to create constraints with an uninitialized \"from\" dimension anchor.");
}, },
(_, Self::Uninitialized) => { (_, Self::Uninitialized) => {
panic!("Attempted to create constraints with an uninitialized \"to\" dimension anchor."); panic!("Attempted to create constraints with an uninitialized \"to\" dimension anchor.");
} }

View file

@ -1,5 +1,5 @@
use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::id; use crate::foundation::id;
@ -41,37 +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 { Self::Leading(unsafe { ShareId::from_ptr(msg_send![view, leadingAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Left(unsafe { ShareId::from_ptr(msg_send![view, leftAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Trailing(unsafe { ShareId::from_ptr(msg_send![view, trailingAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Right(unsafe { ShareId::from_ptr(msg_send![view, rightAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Center(unsafe { ShareId::from_ptr(msg_send![view, centerXAnchor]) })
ShareId::from_ptr(msg_send![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
@ -84,68 +74,72 @@ impl LayoutAnchorX {
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
// kept separate for readability reasons. // kept separate for readability reasons.
(Self::Leading(from), Self::Leading(to)) | (Self::Leading(from), Self::Trailing(to)) | (Self::Leading(from), Self::Leading(to))
(Self::Leading(from), Self::Center(to)) => { | (Self::Leading(from), Self::Trailing(to))
| (Self::Leading(from), Self::Center(to)) => LayoutConstraint::new(handler(from, to)),
(Self::Trailing(from), Self::Trailing(to))
| (Self::Trailing(from), Self::Leading(to))
| (Self::Trailing(from), Self::Center(to)) => LayoutConstraint::new(handler(from, to)),
(Self::Left(from), Self::Left(to)) | (Self::Left(from), Self::Right(to)) | (Self::Left(from), Self::Center(to)) => {
LayoutConstraint::new(handler(from, to)) LayoutConstraint::new(handler(from, to))
}, },
(Self::Trailing(from), Self::Trailing(to)) | (Self::Trailing(from), Self::Leading(to)) | (Self::Right(from), Self::Right(to))
(Self::Trailing(from), Self::Center(to)) => { | (Self::Right(from), Self::Left(to))
LayoutConstraint::new(handler(from, to)) | (Self::Right(from), Self::Center(to)) => LayoutConstraint::new(handler(from, to)),
},
(Self::Left(from), Self::Left(to)) | (Self::Left(from), Self::Right(to)) | (Self::Center(from), Self::Center(to))
(Self::Left(from), Self::Center(to)) => { | (Self::Center(from), Self::Leading(to))
LayoutConstraint::new(handler(from, to)) | (Self::Center(from), Self::Trailing(to))
}, | (Self::Center(from), Self::Left(to))
| (Self::Center(from), Self::Right(to)) => LayoutConstraint::new(handler(from, to)),
(Self::Right(from), Self::Right(to)) | (Self::Right(from), Self::Left(to)) |
(Self::Right(from), Self::Center(to)) => {
LayoutConstraint::new(handler(from, to))
},
(Self::Center(from), Self::Center(to)) | (Self::Center(from), Self::Leading(to)) |
(Self::Center(from), Self::Trailing(to)) | (Self::Center(from), Self::Left(to)) |
(Self::Center(from), Self::Right(to)) => {
LayoutConstraint::new(handler(from, to))
},
// These anchors explicitly cannot be attached to each other, as it results in // These anchors explicitly cannot be attached to each other, as it results in
// undefined/unexpected layout behavior when a system has differing ltr/rtl setups. // undefined/unexpected layout behavior when a system has differing ltr/rtl setups.
(Self::Leading(_), Self::Left(_)) | (Self::Left(_), Self::Leading(_)) => { (Self::Leading(_), Self::Left(_)) | (Self::Left(_), Self::Leading(_)) => {
panic!(r#" panic!(
r#"
Attempted to attach a "leading" constraint to a "left" constraint. This will Attempted to attach a "leading" constraint to a "left" constraint. This will
result in undefined behavior for LTR and RTL system settings, and Cacao blocks this. result in undefined behavior for LTR and RTL system settings, and Cacao blocks this.
Use either left/right or leading/trailing. Use either left/right or leading/trailing.
"#); "#
);
}, },
(Self::Leading(_), Self::Right(_)) | (Self::Right(_), Self::Leading(_)) => { (Self::Leading(_), Self::Right(_)) | (Self::Right(_), Self::Leading(_)) => {
panic!(r#" panic!(
r#"
Attempted to attach a "leading" constraint to a "right" constraint. This will Attempted to attach a "leading" constraint to a "right" constraint. This will
result in undefined behavior for LTR and RTL system settings, and Cacao blocks this. result in undefined behavior for LTR and RTL system settings, and Cacao blocks this.
Use either left/right or leading/trailing. Use either left/right or leading/trailing.
"#); "#
);
}, },
(Self::Trailing(_), Self::Left(_)) | (Self::Left(_), Self::Trailing(_)) => { (Self::Trailing(_), Self::Left(_)) | (Self::Left(_), Self::Trailing(_)) => {
panic!(r#" panic!(
r#"
Attempted to attach a "trailing" constraint to a "left" constraint. This will Attempted to attach a "trailing" constraint to a "left" constraint. This will
result in undefined behavior for LTR and RTL system settings, and Cacao blocks this. result in undefined behavior for LTR and RTL system settings, and Cacao blocks this.
Use either left/right or leading/trailing. Use either left/right or leading/trailing.
"#); "#
);
}, },
(Self::Trailing(_), Self::Right(_)) | (Self::Right(_), Self::Trailing(_)) => { (Self::Trailing(_), Self::Right(_)) | (Self::Right(_), Self::Trailing(_)) => {
panic!(r#" panic!(
r#"
Attempted to attach a "trailing" constraint to a "right" constraint. This will Attempted to attach a "trailing" constraint to a "right" constraint. This will
result in undefined behavior for LTR and RTL system settings, and Cacao blocks this. result in undefined behavior for LTR and RTL system settings, and Cacao blocks this.
Use either left/right or leading/trailing. Use either left/right or leading/trailing.
"#); "#
);
}, },
// If anything is attempted with an uninitialized anchor, then block it. // If anything is attempted with an uninitialized anchor, then block it.

View file

@ -1,7 +1,7 @@
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use crate::foundation::id; use crate::foundation::id;
use crate::layout::{LayoutAnchorX, LayoutAnchorY, LayoutAnchorDimension}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
use crate::utils::os; use crate::utils::os;
/// A SafeAreaLayoutGuide should exist on all view types, and ensures that there are anchor points /// A SafeAreaLayoutGuide should exist on all view types, and ensures that there are anchor points

View file

@ -2,13 +2,13 @@
//! heirarchies. //! heirarchies.
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use core_graphics::geometry::{CGRect, CGPoint, CGSize}; use core_graphics::geometry::{CGPoint, CGRect, CGSize};
use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, to_bool, YES, NO, NSArray, NSString}; use crate::foundation::{id, nil, to_bool, NSArray, NSString, NO, YES};
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::objc_access::ObjcAccess; use crate::objc_access::ObjcAccess;
@ -36,7 +36,7 @@ pub trait Layout: ObjcAccess {
fn add_subview<V: Layout>(&self, view: &V) { fn add_subview<V: Layout>(&self, view: &V) {
self.with_backing_obj_mut(|backing_node| { self.with_backing_obj_mut(|backing_node| {
view.with_backing_obj_mut(|subview_node| unsafe { view.with_backing_obj_mut(|subview_node| unsafe {
let _: () = msg_send![backing_node, addSubview:subview_node]; let _: () = msg_send![backing_node, addSubview: subview_node];
}); });
}); });
} }
@ -57,7 +57,7 @@ pub trait Layout: ObjcAccess {
let frame: CGRect = rect.into(); let frame: CGRect = rect.into();
self.with_backing_obj_mut(move |backing_node| unsafe { self.with_backing_obj_mut(move |backing_node| unsafe {
let _: () = msg_send![backing_node, setFrame:frame]; let _: () = msg_send![backing_node, setFrame: frame];
}); });
} }
@ -93,21 +93,13 @@ pub trait Layout: ObjcAccess {
/// Note that this can report `false` if an ancestor widget is hidden, thus hiding this - to check in /// Note that this can report `false` if an ancestor widget is hidden, thus hiding this - to check in
/// that case, you may want `is_hidden_or_ancestor_is_hidden()`. /// that case, you may want `is_hidden_or_ancestor_is_hidden()`.
fn is_hidden(&self) -> bool { fn is_hidden(&self) -> bool {
self.get_from_backing_obj(|obj| { self.get_from_backing_obj(|obj| to_bool(unsafe { msg_send![obj, isHidden] }))
to_bool(unsafe {
msg_send![obj, isHidden]
})
})
} }
/// Returns whether this is hidden, *or* whether an ancestor view is hidden. /// Returns whether this is hidden, *or* whether an ancestor view is hidden.
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
fn is_hidden_or_ancestor_is_hidden(&self) -> bool { fn is_hidden_or_ancestor_is_hidden(&self) -> bool {
self.get_from_backing_obj(|obj| { self.get_from_backing_obj(|obj| to_bool(unsafe { msg_send![obj, isHiddenOrHasHiddenAncestor] }))
to_bool(unsafe {
msg_send![obj, isHiddenOrHasHiddenAncestor]
})
})
} }
/// Register this view for drag and drop operations. /// Register this view for drag and drop operations.
@ -116,10 +108,14 @@ pub trait Layout: ObjcAccess {
/// currently to avoid compile issues. /// currently to avoid compile issues.
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
fn register_for_dragged_types(&self, types: &[PasteboardType]) { fn register_for_dragged_types(&self, types: &[PasteboardType]) {
let types: NSArray = types.into_iter().map(|t| { let types: NSArray = types
.into_iter()
.map(|t| {
let x: NSString = (*t).into(); let x: NSString = (*t).into();
x.into() x.into()
}).collect::<Vec<id>>().into(); })
.collect::<Vec<id>>()
.into();
self.with_backing_obj_mut(|obj| unsafe { self.with_backing_obj_mut(|obj| unsafe {
let _: () = msg_send![obj, registerForDraggedTypes:&*types]; let _: () = msg_send![obj, registerForDraggedTypes:&*types];
@ -172,7 +168,7 @@ pub trait Layout: ObjcAccess {
let value: CGFloat = value.into(); let value: CGFloat = value.into();
self.with_backing_obj_mut(|obj| unsafe { self.with_backing_obj_mut(|obj| unsafe {
let _: () = msg_send![obj, setAlphaValue:value]; let _: () = msg_send![obj, setAlphaValue: value];
}); });
} }
} }

View file

@ -1,5 +1,5 @@
use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object; use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::id; use crate::foundation::id;
@ -31,23 +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 { Self::Top(unsafe { ShareId::from_ptr(msg_send![view, topAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Bottom(unsafe { ShareId::from_ptr(msg_send![view, bottomAnchor]) })
ShareId::from_ptr(msg_send![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 { Self::Center(unsafe { ShareId::from_ptr(msg_send![view, centerYAnchor]) })
ShareId::from_ptr(msg_send![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
@ -58,16 +52,15 @@ impl LayoutAnchorY {
F: Fn(&ShareId<Object>, &ShareId<Object>) -> id F: Fn(&ShareId<Object>, &ShareId<Object>) -> id
{ {
match (self, anchor_to) { match (self, anchor_to) {
(Self::Top(from), Self::Top(to)) | (Self::Top(from), Self::Bottom(to)) | (Self::Top(from), Self::Top(to))
(Self::Top(from), Self::Center(to)) | | (Self::Top(from), Self::Bottom(to))
| (Self::Top(from), Self::Center(to))
(Self::Bottom(from), Self::Bottom(to)) | (Self::Bottom(from), Self::Top(to)) | | (Self::Bottom(from), Self::Bottom(to))
(Self::Bottom(from), Self::Center(to)) | | (Self::Bottom(from), Self::Top(to))
| (Self::Bottom(from), Self::Center(to))
(Self::Center(from), Self::Center(to)) | (Self::Center(from), Self::Top(to)) | | (Self::Center(from), Self::Center(to))
(Self::Center(from), Self::Bottom(to)) => { | (Self::Center(from), Self::Top(to))
LayoutConstraint::new(handler(from, to)) | (Self::Center(from), Self::Bottom(to)) => LayoutConstraint::new(handler(from, to)),
},
(Self::Uninitialized, Self::Uninitialized) => { (Self::Uninitialized, Self::Uninitialized) => {
panic!("Attempted to create constraints with uninitialized \"from\" and \"to\" y anchors."); panic!("Attempted to create constraints with uninitialized \"from\" and \"to\" y anchors.");

View file

@ -3,7 +3,6 @@
#![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))]
// 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.
@ -93,9 +92,9 @@
pub use core_foundation; pub use core_foundation;
pub use core_graphics; pub use core_graphics;
pub use lazy_static;
pub use objc; pub use objc;
pub use url; pub use url;
pub use lazy_static;
//#[cfg(all(feature = "appkit", feature = "uikit", not(feature = "doc_cfg")))] //#[cfg(all(feature = "appkit", feature = "uikit", not(feature = "doc_cfg")))]
//compile_error!("The \"appkit\" and \"uikit\" features cannot be enabled together. Pick one. :)"); //compile_error!("The \"appkit\" and \"uikit\" features cannot be enabled together. Pick one. :)");
@ -153,8 +152,8 @@ pub mod layout;
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
pub mod listview; pub mod listview;
pub mod networking; pub mod networking;
pub(crate) mod objc_access;
pub mod notification_center; pub mod notification_center;
pub(crate) mod objc_access;
#[cfg(feature = "appkit")] #[cfg(feature = "appkit")]
pub mod pasteboard; pub mod pasteboard;

View file

@ -1,6 +1,6 @@
use objc_id::Id;
use objc::runtime::Object; use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use block::ConcreteBlock; use block::ConcreteBlock;
@ -56,9 +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 { let action = RowAction(unsafe { Id::from_ptr(action) });
Id::from_ptr(action)
});
handler(action, row as usize); handler(action, row as usize);
}); });
@ -88,7 +86,7 @@ impl RowAction {
let color: id = color.as_ref().into(); let color: id = color.as_ref().into();
unsafe { unsafe {
let _: () = msg_send![&*self.0, setBackgroundColor:color]; let _: () = msg_send![&*self.0, setBackgroundColor: color];
} }
} }
@ -97,7 +95,7 @@ impl RowAction {
let style = style as NSUInteger; let style = style as NSUInteger;
unsafe { unsafe {
let _: () = msg_send![&*self.0, setStyle:style]; let _: () = msg_send![&*self.0, setStyle: style];
} }
} }

View file

@ -11,29 +11,22 @@ 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, msg_send}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::appkit::menu::{Menu, MenuItem}; use crate::appkit::menu::{Menu, MenuItem};
use crate::foundation::{load_or_register_class, id, nil, YES, NO, NSArray, NSInteger, NSUInteger};
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::listview::{ use crate::foundation::{id, load_or_register_class, nil, NSArray, NSInteger, NSUInteger, NO, YES};
LISTVIEW_DELEGATE_PTR, use crate::listview::{ListViewDelegate, RowEdge, LISTVIEW_DELEGATE_PTR};
ListViewDelegate, RowEdge
};
use crate::utils::load; use crate::utils::load;
/// Determines the number of items by way of the backing data source (the Rust struct). /// Determines the number of items by way of the backing data source (the Rust struct).
extern fn number_of_items<T: ListViewDelegate>( extern "C" fn number_of_items<T: ListViewDelegate>(this: &Object, _: Sel, _: id) -> NSInteger {
this: &Object,
_: Sel,
_: id
) -> NSInteger {
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR); let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
view.number_of_items() as NSInteger view.number_of_items() as NSInteger
} }
extern fn view_for_column<T: ListViewDelegate>( extern "C" fn view_for_column<T: ListViewDelegate>(
this: &Object, this: &Object,
_: Sel, _: Sel,
_table_view: id, _table_view: id,
@ -59,12 +52,10 @@ extern fn view_for_column<T: ListViewDelegate>(
// //
// @TODO: Finish investing the `Rc` approach, might be able to just take // @TODO: Finish investing the `Rc` approach, might be able to just take
// ownership and rely on Rust being correct. // ownership and rely on Rust being correct.
item.objc.get(|obj| unsafe { item.objc.get(|obj| unsafe { msg_send![obj, self] })
msg_send![obj, self]
})
} }
extern fn will_display_cell<T: ListViewDelegate>( extern "C" fn will_display_cell<T: ListViewDelegate>(
this: &Object, this: &Object,
_: Sel, _: Sel,
_table_view: id, _table_view: id,
@ -76,11 +67,7 @@ extern fn will_display_cell<T: ListViewDelegate>(
view.will_display_item(item as usize); view.will_display_item(item as usize);
} }
extern fn menu_needs_update<T: ListViewDelegate>( extern "C" fn menu_needs_update<T: ListViewDelegate>(this: &Object, _: Sel, menu: id) {
this: &Object,
_: Sel,
menu: id
) {
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR); let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
let items = view.context_menu(); let items = view.context_menu();
let _ = Menu::append(menu, items); let _ = Menu::append(menu, items);
@ -92,7 +79,7 @@ extern fn menu_needs_update<T: ListViewDelegate>(
/// The other less obvious way is to subclass and override the `shouldSelectRow:` method; here, we /// The other less obvious way is to subclass and override the `shouldSelectRow:` method; here, we
/// simply assume things are selectable and call our delegate as if things were selected. This may /// simply assume things are selectable and call our delegate as if things were selected. This may
/// need to change in the future, but it works well enough for now. /// need to change in the future, but it works well enough for now.
extern fn select_row<T: ListViewDelegate>( extern "C" fn select_row<T: ListViewDelegate>(
this: &Object, this: &Object,
_: Sel, _: Sel,
_table_view: id, _table_view: id,
@ -103,11 +90,7 @@ extern fn select_row<T: ListViewDelegate>(
YES YES
}*/ }*/
extern fn selection_did_change<T: ListViewDelegate>( extern "C" fn selection_did_change<T: ListViewDelegate>(this: &Object, _: Sel, notification: id) {
this: &Object,
_: Sel,
notification: id
) {
let selected_row: NSInteger = unsafe { let selected_row: NSInteger = unsafe {
let tableview: id = msg_send![notification, object]; let tableview: id = msg_send![notification, object];
msg_send![tableview, selectedRow] msg_send![tableview, selectedRow]
@ -121,7 +104,7 @@ extern fn selection_did_change<T: ListViewDelegate>(
} }
} }
extern fn row_actions_for_row<T: ListViewDelegate>( extern "C" fn row_actions_for_row<T: ListViewDelegate>(
this: &Object, this: &Object,
_: Sel, _: Sel,
_table_view: id, _table_view: id,
@ -131,7 +114,8 @@ extern fn row_actions_for_row<T: ListViewDelegate>(
let edge: RowEdge = edge.into(); let edge: RowEdge = edge.into();
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR); let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
let mut ids: NSArray = view.actions_for(row as usize, edge) let mut ids: NSArray = view
.actions_for(row as usize, edge)
.iter_mut() .iter_mut()
.map(|action| &*action.0) .map(|action| &*action.0)
.collect::<Vec<&Object>>() .collect::<Vec<&Object>>()
@ -141,20 +125,21 @@ extern 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 fn enforce_normalcy(_: &Object, _: Sel) -> BOOL { extern "C" fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
return YES; return YES;
} }
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn dragging_entered<T: 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::from_ptr(info) }
}).into() })
.into()
} }
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern 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 { match view.prepare_for_drag_operation(DragInfo {
@ -166,7 +151,7 @@ extern fn prepare_for_drag_operation<T: ListViewDelegate>(this: &mut Object, _:
} }
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern 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 { match view.perform_drag_operation(DragInfo {
@ -178,7 +163,7 @@ extern fn perform_drag_operation<T: ListViewDelegate>(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 fn conclude_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) { extern "C" fn conclude_drag_operation<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) {
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 {
@ -187,7 +172,7 @@ extern fn conclude_drag_operation<T: ListViewDelegate>(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 fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) { extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, info: id) {
let view = load::<T>(this, LISTVIEW_DELEGATE_PTR); let view = load::<T>(this, LISTVIEW_DELEGATE_PTR);
view.dragging_exited(DragInfo { view.dragging_exited(DragInfo {
@ -209,9 +194,7 @@ pub(crate) fn register_listview_class() -> *const Class {
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
unsafe { unsafe { VIEW_CLASS }
VIEW_CLASS
}
} }
/// Injects an `NSTableView` subclass, with some callback and pointer ivars for what we /// Injects an `NSTableView` subclass, with some callback and pointer ivars for what we
@ -222,25 +205,58 @@ pub(crate) fn register_listview_class_with_delegate<T: ListViewDelegate>(instanc
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 fn(&Object, _) -> BOOL); decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
// Tableview-specific // Tableview-specific
decl.add_method(sel!(numberOfRowsInTableView:), number_of_items::<T> as extern fn(&Object, _, id) -> NSInteger); decl.add_method(
decl.add_method(sel!(tableView:willDisplayCell:forTableColumn:row:), will_display_cell::<T> as extern fn(&Object, _, id, id, id, NSInteger)); sel!(numberOfRowsInTableView:),
decl.add_method(sel!(tableView:viewForTableColumn:row:), view_for_column::<T> as extern fn(&Object, _, id, id, NSInteger) -> id); number_of_items::<T> as extern "C" fn(&Object, _, id) -> NSInteger
decl.add_method(sel!(tableViewSelectionDidChange:), selection_did_change::<T> as extern fn(&Object, _, id)); );
decl.add_method(sel!(tableView:rowActionsForRow:edge:), row_actions_for_row::<T> as extern fn(&Object, _, id, NSInteger, NSInteger) -> id); decl.add_method(
sel!(tableView:willDisplayCell:forTableColumn:row:),
will_display_cell::<T> as extern "C" fn(&Object, _, id, id, id, NSInteger)
);
decl.add_method(
sel!(tableView:viewForTableColumn:row:),
view_for_column::<T> as extern "C" fn(&Object, _, id, id, NSInteger) -> id
);
decl.add_method(
sel!(tableViewSelectionDidChange:),
selection_did_change::<T> as extern "C" fn(&Object, _, id)
);
decl.add_method(
sel!(tableView:rowActionsForRow:edge:),
row_actions_for_row::<T> as extern "C" fn(&Object, _, id, NSInteger, NSInteger) -> id
);
// 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(sel!(menuNeedsUpdate:), menu_needs_update::<T> as extern fn(&Object, _, id)); decl.add_method(
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(sel!(draggingEntered:), dragging_entered::<T> as extern fn (&mut Object, _, _) -> NSUInteger); decl.add_method(
decl.add_method(sel!(prepareForDragOperation:), prepare_for_drag_operation::<T> as extern fn (&mut Object, _, _) -> BOOL); sel!(draggingEntered:),
decl.add_method(sel!(performDragOperation:), perform_drag_operation::<T> as extern fn (&mut Object, _, _) -> BOOL); dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
decl.add_method(sel!(concludeDragOperation:), conclude_drag_operation::<T> as extern fn (&mut Object, _, _)); );
decl.add_method(sel!(draggingExited:), dragging_exited::<T> as extern fn (&mut Object, _, _)); 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 file

@ -63,7 +63,9 @@ impl Into<RowEdge> for NSInteger {
// @TODO: This *should* be unreachable, provided macOS doesn't start // @TODO: This *should* be unreachable, provided macOS doesn't start
// letting people swipe from vertical directions to reveal stuff. Have to // letting people swipe from vertical directions to reveal stuff. Have to
// feel like there's a better way to do this, though... // feel like there's a better way to do this, though...
_ => { unreachable!(); } _ => {
unreachable!();
}
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more