commit
1993226f57
23
.github/workflows/ci.yml
vendored
Normal file
23
.github/workflows/ci.yml
vendored
Normal 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
|
|
@ -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) }
|
||||||
|
|
|
@ -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,20 +110,24 @@ 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]
|
||||||
LayoutConstraint::activate(frame);
|
.iter()
|
||||||
|
.map(|frame| {
|
||||||
|
LayoutConstraint::activate(frame);
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
frame[0].animator.clone(),
|
frame[0].animator.clone(),
|
||||||
frame[1].animator.clone(),
|
frame[1].animator.clone(),
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,31 +15,36 @@ 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()
|
||||||
Msg::Clear => "C",
|
.map(|y| {
|
||||||
Msg::Add => "+",
|
let button = button(
|
||||||
Msg::Subtract => "-",
|
match y {
|
||||||
Msg::Multiply => "X",
|
Msg::Clear => "C",
|
||||||
Msg::Divide => "/",
|
Msg::Add => "+",
|
||||||
Msg::Invert => "+/-",
|
Msg::Subtract => "-",
|
||||||
Msg::Mod => "%",
|
Msg::Multiply => "X",
|
||||||
Msg::Push(i) if *i == 1 => "1",
|
Msg::Divide => "/",
|
||||||
Msg::Push(i) if *i == 2 => "2",
|
Msg::Invert => "+/-",
|
||||||
Msg::Push(i) if *i == 3 => "3",
|
Msg::Mod => "%",
|
||||||
Msg::Push(i) if *i == 4 => "4",
|
Msg::Push(i) if *i == 1 => "1",
|
||||||
Msg::Push(i) if *i == 5 => "5",
|
Msg::Push(i) if *i == 2 => "2",
|
||||||
Msg::Push(i) if *i == 6 => "6",
|
Msg::Push(i) if *i == 3 => "3",
|
||||||
Msg::Push(i) if *i == 7 => "7",
|
Msg::Push(i) if *i == 4 => "4",
|
||||||
Msg::Push(i) if *i == 8 => "8",
|
Msg::Push(i) if *i == 5 => "5",
|
||||||
Msg::Push(i) if *i == 9 => "9",
|
Msg::Push(i) if *i == 6 => "6",
|
||||||
_ => "W"
|
Msg::Push(i) if *i == 7 => "7",
|
||||||
|
Msg::Push(i) if *i == 8 => "8",
|
||||||
|
Msg::Push(i) if *i == 9 => "9",
|
||||||
|
_ => "W"
|
||||||
|
},
|
||||||
|
y.clone()
|
||||||
|
);
|
||||||
|
|
||||||
}, y.clone());
|
view.add_subview(&button);
|
||||||
|
button
|
||||||
view.add_subview(&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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.)
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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![])
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,31 +11,34 @@ 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");
|
{
|
||||||
item.set_title("General");
|
let mut item = ToolbarItem::new("general");
|
||||||
|
item.set_title("General");
|
||||||
|
|
||||||
let icon = Image::toolbar_icon(MacSystemIcon::PreferencesGeneral, "General");
|
let icon = Image::toolbar_icon(MacSystemIcon::PreferencesGeneral, "General");
|
||||||
item.set_image(icon);
|
item.set_image(icon);
|
||||||
|
|
||||||
item.set_action(|| {
|
item.set_action(|| {
|
||||||
dispatch_ui(Message::SwitchPreferencesToGeneralPane);
|
dispatch_ui(Message::SwitchPreferencesToGeneralPane);
|
||||||
});
|
});
|
||||||
|
|
||||||
item
|
item
|
||||||
}, {
|
},
|
||||||
let mut item = ToolbarItem::new("advanced");
|
{
|
||||||
item.set_title("Advanced");
|
let mut item = ToolbarItem::new("advanced");
|
||||||
|
item.set_title("Advanced");
|
||||||
|
|
||||||
let icon = Image::toolbar_icon(MacSystemIcon::PreferencesAdvanced, "Advanced");
|
let icon = Image::toolbar_icon(MacSystemIcon::PreferencesAdvanced, "Advanced");
|
||||||
item.set_image(icon);
|
item.set_image(icon);
|
||||||
|
|
||||||
item.set_action(|| {
|
item.set_action(|| {
|
||||||
dispatch_ui(Message::SwitchPreferencesToAdvancedPane);
|
dispatch_ui(Message::SwitchPreferencesToAdvancedPane);
|
||||||
});
|
});
|
||||||
|
|
||||||
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!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
dispatch_ui(Message::MarkTodoIncomplete(row));
|
"Mark Incomplete",
|
||||||
}));
|
RowActionStyle::Destructive,
|
||||||
|
move |_action, 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(
|
||||||
dispatch_ui(Message::MarkTodoComplete(row));
|
"Mark Complete",
|
||||||
}));
|
RowActionStyle::Regular,
|
||||||
|
move |_action, row| {
|
||||||
|
dispatch_ui(Message::MarkTodoComplete(row));
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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.),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
6
rustfmt.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
max_width = 130
|
||||||
|
match_block_trailing_comma = true
|
||||||
|
|
||||||
|
# Nightly
|
||||||
|
overflow_delimited_expr = true
|
||||||
|
trailing_comma = "Never"
|
|
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ impl Alert {
|
||||||
/// Shows this alert as a modal.
|
/// Shows this alert as a modal.
|
||||||
pub fn show(&self) {
|
pub fn show(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*self.0, runModal];
|
let _: () = msg_send![&*self.0, runModal];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,14 +121,14 @@ impl From<PresentationOption> for NSUInteger {
|
||||||
PresentationOption::Default => 0,
|
PresentationOption::Default => 0,
|
||||||
PresentationOption::AutoHideDock => (1 << 0),
|
PresentationOption::AutoHideDock => (1 << 0),
|
||||||
PresentationOption::HideDock => (1 << 1),
|
PresentationOption::HideDock => (1 << 1),
|
||||||
PresentationOption::AutoHideMenuBar => (1 << 2),
|
PresentationOption::AutoHideMenuBar => (1 << 2),
|
||||||
PresentationOption::HideMenuBar => (1 << 3),
|
PresentationOption::HideMenuBar => (1 << 3),
|
||||||
PresentationOption::DisableAppleMenu => (1 << 4),
|
PresentationOption::DisableAppleMenu => (1 << 4),
|
||||||
PresentationOption::DisableProcessSwitching => (1 << 5),
|
PresentationOption::DisableProcessSwitching => (1 << 5),
|
||||||
PresentationOption::DisableForceQuit => (1 << 6),
|
PresentationOption::DisableForceQuit => (1 << 6),
|
||||||
PresentationOption::DisableSessionTermination => (1 << 7),
|
PresentationOption::DisableSessionTermination => (1 << 7),
|
||||||
PresentationOption::DisableHideApplication => (1 << 8),
|
PresentationOption::DisableHideApplication => (1 << 8),
|
||||||
PresentationOption::DisableMenuBarTransparency => (1 << 9),
|
PresentationOption::DisableMenuBarTransparency => (1 << 9),
|
||||||
PresentationOption::FullScreen => (1 << 10),
|
PresentationOption::FullScreen => (1 << 10),
|
||||||
PresentationOption::AutoHideToolbar => (1 << 11),
|
PresentationOption::AutoHideToolbar => (1 << 11),
|
||||||
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
|
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
|
||||||
|
@ -142,14 +142,14 @@ impl From<&PresentationOption> for NSUInteger {
|
||||||
PresentationOption::Default => 0,
|
PresentationOption::Default => 0,
|
||||||
PresentationOption::AutoHideDock => (1 << 0),
|
PresentationOption::AutoHideDock => (1 << 0),
|
||||||
PresentationOption::HideDock => (1 << 1),
|
PresentationOption::HideDock => (1 << 1),
|
||||||
PresentationOption::AutoHideMenuBar => (1 << 2),
|
PresentationOption::AutoHideMenuBar => (1 << 2),
|
||||||
PresentationOption::HideMenuBar => (1 << 3),
|
PresentationOption::HideMenuBar => (1 << 3),
|
||||||
PresentationOption::DisableAppleMenu => (1 << 4),
|
PresentationOption::DisableAppleMenu => (1 << 4),
|
||||||
PresentationOption::DisableProcessSwitching => (1 << 5),
|
PresentationOption::DisableProcessSwitching => (1 << 5),
|
||||||
PresentationOption::DisableForceQuit => (1 << 6),
|
PresentationOption::DisableForceQuit => (1 << 6),
|
||||||
PresentationOption::DisableSessionTermination => (1 << 7),
|
PresentationOption::DisableSessionTermination => (1 << 7),
|
||||||
PresentationOption::DisableHideApplication => (1 << 8),
|
PresentationOption::DisableHideApplication => (1 << 8),
|
||||||
PresentationOption::DisableMenuBarTransparency => (1 << 9),
|
PresentationOption::DisableMenuBarTransparency => (1 << 9),
|
||||||
PresentationOption::FullScreen => (1 << 10),
|
PresentationOption::FullScreen => (1 << 10),
|
||||||
PresentationOption::AutoHideToolbar => (1 << 11),
|
PresentationOption::AutoHideToolbar => (1 << 11),
|
||||||
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
|
PresentationOption::DisableCursorLocationAssistance => (1 << 12)
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
])
|
]),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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, _, _));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -31,11 +31,9 @@ pub enum DragOperation {
|
||||||
Move,
|
Move,
|
||||||
|
|
||||||
/// The data can be deleted.
|
/// The data can be deleted.
|
||||||
Delete,
|
Delete // All of the above.
|
||||||
|
// @TODO: NSUIntegerMax, a tricky beast
|
||||||
// All of the above.
|
// Every
|
||||||
// @TODO: NSUIntegerMax, a tricky beast
|
|
||||||
// Every
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DragOperation> for NSUInteger {
|
impl From<DragOperation> for NSUInteger {
|
||||||
|
@ -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])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
pub mod enums;
|
pub mod enums;
|
||||||
pub use enums::*;
|
pub use enums::*;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -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| {
|
||||||
transform(item)
|
let item: id = unsafe { msg_send![objc, objectAtIndex: index] };
|
||||||
}).collect()
|
transform(item)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl From<NSURLBookmarkCreationOption> for NSUInteger {
|
||||||
fn from(flag: NSURLBookmarkCreationOption) -> NSUInteger {
|
fn from(flag: NSURLBookmarkCreationOption) -> NSUInteger {
|
||||||
match flag {
|
match flag {
|
||||||
NSURLBookmarkCreationOption::Minimal => 1u64 << 9,
|
NSURLBookmarkCreationOption::Minimal => 1u64 << 9,
|
||||||
NSURLBookmarkCreationOption::SuitableForBookmarkFile => 1u64 << 10,
|
NSURLBookmarkCreationOption::SuitableForBookmarkFile => 1u64 << 10,
|
||||||
NSURLBookmarkCreationOption::SecurityScoped => 1 << 11,
|
NSURLBookmarkCreationOption::SecurityScoped => 1 << 11,
|
||||||
NSURLBookmarkCreationOption::SecurityScopedReadOnly => 1 << 12
|
NSURLBookmarkCreationOption::SecurityScopedReadOnly => 1 << 12
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl From<&NSURLBookmarkCreationOption> for NSUInteger {
|
||||||
fn from(flag: &NSURLBookmarkCreationOption) -> NSUInteger {
|
fn from(flag: &NSURLBookmarkCreationOption) -> NSUInteger {
|
||||||
match flag {
|
match flag {
|
||||||
NSURLBookmarkCreationOption::Minimal => 1u64 << 9,
|
NSURLBookmarkCreationOption::Minimal => 1u64 << 9,
|
||||||
NSURLBookmarkCreationOption::SuitableForBookmarkFile => 1u64 << 10,
|
NSURLBookmarkCreationOption::SuitableForBookmarkFile => 1u64 << 10,
|
||||||
NSURLBookmarkCreationOption::SecurityScoped => 1 << 11,
|
NSURLBookmarkCreationOption::SecurityScoped => 1 << 11,
|
||||||
NSURLBookmarkCreationOption::SecurityScopedReadOnly => 1 << 12
|
NSURLBookmarkCreationOption::SecurityScopedReadOnly => 1 << 12
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl MacSystemIcon {
|
||||||
|
|
||||||
/// Maps system icons to their SFSymbols-counterparts for use on 11.0+.
|
/// Maps system icons to their SFSymbols-counterparts for use on 11.0+.
|
||||||
pub fn to_sfsymbol_str(&self) -> &'static str {
|
pub fn to_sfsymbol_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
MacSystemIcon::PreferencesGeneral => SFSymbol::GearShape.to_str(),
|
MacSystemIcon::PreferencesGeneral => SFSymbol::GearShape.to_str(),
|
||||||
MacSystemIcon::PreferencesAdvanced => SFSymbol::SliderVertical3.to_str(),
|
MacSystemIcon::PreferencesAdvanced => SFSymbol::SliderVertical3.to_str(),
|
||||||
MacSystemIcon::PreferencesUserAccounts => SFSymbol::AtSymbol.to_str(),
|
MacSystemIcon::PreferencesUserAccounts => SFSymbol::AtSymbol.to_str(),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
let x: NSString = (*t).into();
|
.into_iter()
|
||||||
x.into()
|
.map(|t| {
|
||||||
}).collect::<Vec<id>>().into();
|
let x: NSString = (*t).into();
|
||||||
|
x.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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue