Get app running and test passing after gpui App+Platform restructure
This commit is contained in:
@@ -5,7 +5,6 @@ mod fonts;
|
||||
mod geometry;
|
||||
mod platform;
|
||||
mod renderer;
|
||||
mod runner;
|
||||
mod sprite_cache;
|
||||
mod window;
|
||||
|
||||
@@ -13,15 +12,15 @@ use cocoa::base::{BOOL, NO, YES};
|
||||
pub use dispatcher::Dispatcher;
|
||||
pub use fonts::FontSystem;
|
||||
use platform::MacPlatform;
|
||||
pub use runner::Runner;
|
||||
use std::sync::Arc;
|
||||
use window::Window;
|
||||
|
||||
pub fn app() -> impl super::Platform {
|
||||
pub fn platform() -> Arc<dyn super::Platform> {
|
||||
MacPlatform::new()
|
||||
}
|
||||
|
||||
pub fn runner() -> impl super::Runner {
|
||||
Runner::new()
|
||||
pub fn run() {
|
||||
MacPlatform::run();
|
||||
}
|
||||
|
||||
trait BoolExt {
|
||||
|
||||
@@ -90,13 +90,112 @@ struct Callbacks {
|
||||
}
|
||||
|
||||
impl MacPlatform {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pub fn new() -> Arc<dyn platform::Platform> {
|
||||
let result = Arc::new(Self {
|
||||
dispatcher: Arc::new(Dispatcher),
|
||||
fonts: Arc::new(FontSystem::new()),
|
||||
callbacks: Default::default(),
|
||||
menu_item_actions: Default::default(),
|
||||
});
|
||||
|
||||
unsafe {
|
||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||
let app_delegate: id = msg_send![APP_DELEGATE_CLASS, new];
|
||||
let self_ptr = result.as_ref() as *const Self as *const c_void;
|
||||
app.setDelegate_(app_delegate);
|
||||
(*app).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
|
||||
(*app_delegate).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn run() {
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||
|
||||
app.run();
|
||||
pool.drain();
|
||||
(*app).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
|
||||
(*app.delegate()).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn create_menu_bar(&self, menus: &[Menu]) -> id {
|
||||
let menu_bar = NSMenu::new(nil).autorelease();
|
||||
let mut menu_item_actions = self.menu_item_actions.borrow_mut();
|
||||
menu_item_actions.clear();
|
||||
|
||||
for menu_config in menus {
|
||||
let menu_bar_item = NSMenuItem::new(nil).autorelease();
|
||||
let menu = NSMenu::new(nil).autorelease();
|
||||
|
||||
menu.setTitle_(ns_string(menu_config.name));
|
||||
|
||||
for item_config in menu_config.items {
|
||||
let item;
|
||||
|
||||
match item_config {
|
||||
MenuItem::Separator => {
|
||||
item = NSMenuItem::separatorItem(nil);
|
||||
}
|
||||
MenuItem::Action {
|
||||
name,
|
||||
keystroke,
|
||||
action,
|
||||
} => {
|
||||
if let Some(keystroke) = keystroke {
|
||||
let keystroke = Keystroke::parse(keystroke).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Invalid keystroke for menu item {}:{} - {:?}",
|
||||
menu_config.name, name, err
|
||||
)
|
||||
});
|
||||
|
||||
let mut mask = NSEventModifierFlags::empty();
|
||||
for (modifier, flag) in &[
|
||||
(keystroke.cmd, NSEventModifierFlags::NSCommandKeyMask),
|
||||
(keystroke.ctrl, NSEventModifierFlags::NSControlKeyMask),
|
||||
(keystroke.alt, NSEventModifierFlags::NSAlternateKeyMask),
|
||||
] {
|
||||
if *modifier {
|
||||
mask |= *flag;
|
||||
}
|
||||
}
|
||||
|
||||
item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(
|
||||
ns_string(name),
|
||||
selector("handleGPUIMenuItem:"),
|
||||
ns_string(&keystroke.key),
|
||||
)
|
||||
.autorelease();
|
||||
item.setKeyEquivalentModifierMask_(mask);
|
||||
} else {
|
||||
item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(
|
||||
ns_string(name),
|
||||
selector("handleGPUIMenuItem:"),
|
||||
ns_string(""),
|
||||
)
|
||||
.autorelease();
|
||||
}
|
||||
|
||||
let tag = menu_item_actions.len() as NSInteger;
|
||||
let _: () = msg_send![item, setTag: tag];
|
||||
menu_item_actions.push(action.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
menu.addItem_(item);
|
||||
}
|
||||
|
||||
menu_bar_item.setSubmenu_(menu);
|
||||
menu_bar.addItem_(menu_bar_item);
|
||||
}
|
||||
|
||||
menu_bar
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,23 +220,8 @@ impl platform::Platform for MacPlatform {
|
||||
self.callbacks.borrow_mut().open_files = Some(callback);
|
||||
}
|
||||
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>) {
|
||||
self.callbacks.borrow_mut().finish_launching = Some(on_finish_launching);
|
||||
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||
let app_delegate: id = msg_send![APP_DELEGATE_CLASS, new];
|
||||
|
||||
let self_ptr = self as *const Self as *mut c_void;
|
||||
(*app).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
|
||||
(*app_delegate).set_ivar(MAC_PLATFORM_IVAR, self_ptr);
|
||||
app.setDelegate_(app_delegate);
|
||||
app.run();
|
||||
pool.drain();
|
||||
(*app).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
|
||||
(*app_delegate).set_ivar(MAC_PLATFORM_IVAR, null_mut::<c_void>());
|
||||
}
|
||||
fn on_finish_launching(&self, callback: Box<dyn FnOnce() -> ()>) {
|
||||
self.callbacks.borrow_mut().finish_launching = Some(callback);
|
||||
}
|
||||
|
||||
fn dispatcher(&self) -> Arc<dyn platform::Dispatcher> {
|
||||
@@ -222,84 +306,6 @@ impl platform::Platform for MacPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
impl MacPlatform {
|
||||
unsafe fn create_menu_bar(&self, menus: &[Menu]) -> id {
|
||||
let menu_bar = NSMenu::new(nil).autorelease();
|
||||
let mut menu_item_actions = self.menu_item_actions.borrow_mut();
|
||||
menu_item_actions.clear();
|
||||
|
||||
for menu_config in menus {
|
||||
let menu_bar_item = NSMenuItem::new(nil).autorelease();
|
||||
let menu = NSMenu::new(nil).autorelease();
|
||||
|
||||
menu.setTitle_(ns_string(menu_config.name));
|
||||
|
||||
for item_config in menu_config.items {
|
||||
let item;
|
||||
|
||||
match item_config {
|
||||
MenuItem::Separator => {
|
||||
item = NSMenuItem::separatorItem(nil);
|
||||
}
|
||||
MenuItem::Action {
|
||||
name,
|
||||
keystroke,
|
||||
action,
|
||||
} => {
|
||||
if let Some(keystroke) = keystroke {
|
||||
let keystroke = Keystroke::parse(keystroke).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Invalid keystroke for menu item {}:{} - {:?}",
|
||||
menu_config.name, name, err
|
||||
)
|
||||
});
|
||||
|
||||
let mut mask = NSEventModifierFlags::empty();
|
||||
for (modifier, flag) in &[
|
||||
(keystroke.cmd, NSEventModifierFlags::NSCommandKeyMask),
|
||||
(keystroke.ctrl, NSEventModifierFlags::NSControlKeyMask),
|
||||
(keystroke.alt, NSEventModifierFlags::NSAlternateKeyMask),
|
||||
] {
|
||||
if *modifier {
|
||||
mask |= *flag;
|
||||
}
|
||||
}
|
||||
|
||||
item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(
|
||||
ns_string(name),
|
||||
selector("handleGPUIMenuItem:"),
|
||||
ns_string(&keystroke.key),
|
||||
)
|
||||
.autorelease();
|
||||
item.setKeyEquivalentModifierMask_(mask);
|
||||
} else {
|
||||
item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(
|
||||
ns_string(name),
|
||||
selector("handleGPUIMenuItem:"),
|
||||
ns_string(""),
|
||||
)
|
||||
.autorelease();
|
||||
}
|
||||
|
||||
let tag = menu_item_actions.len() as NSInteger;
|
||||
let _: () = msg_send![item, setTag: tag];
|
||||
menu_item_actions.push(action.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
menu.addItem_(item);
|
||||
}
|
||||
|
||||
menu_bar_item.setSubmenu_(menu);
|
||||
menu_bar.addItem_(menu_bar_item);
|
||||
}
|
||||
|
||||
menu_bar
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_platform(object: &mut Object) -> &MacPlatform {
|
||||
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
|
||||
assert!(!platform_ptr.is_null());
|
||||
|
||||
@@ -22,24 +22,13 @@ use async_task::Runnable;
|
||||
pub use event::Event;
|
||||
use std::{ops::Range, path::PathBuf, rc::Rc, sync::Arc};
|
||||
|
||||
pub trait Runner {
|
||||
fn on_finish_launching<F: 'static + FnOnce()>(self, callback: F) -> Self;
|
||||
fn on_menu_command<F: 'static + FnMut(&str)>(self, callback: F) -> Self;
|
||||
fn on_become_active<F: 'static + FnMut()>(self, callback: F) -> Self;
|
||||
fn on_resign_active<F: 'static + FnMut()>(self, callback: F) -> Self;
|
||||
fn on_event<F: 'static + FnMut(Event) -> bool>(self, callback: F) -> Self;
|
||||
fn on_open_files<F: 'static + FnMut(Vec<PathBuf>)>(self, callback: F) -> Self;
|
||||
fn set_menus(self, menus: &[Menu]) -> Self;
|
||||
fn run(self);
|
||||
}
|
||||
|
||||
pub trait Platform {
|
||||
fn on_menu_command(&self, callback: Box<dyn FnMut(&str)>);
|
||||
fn on_become_active(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>);
|
||||
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||
fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>);
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>);
|
||||
fn on_finish_launching(&self, callback: Box<dyn FnOnce() -> ()>);
|
||||
|
||||
fn dispatcher(&self) -> Arc<dyn Dispatcher>;
|
||||
fn fonts(&self) -> Arc<dyn FontSystem>;
|
||||
|
||||
@@ -39,9 +39,7 @@ impl super::Platform for Platform {
|
||||
|
||||
fn on_open_files(&self, _: Box<dyn FnMut(Vec<std::path::PathBuf>)>) {}
|
||||
|
||||
fn run(&self, _on_finish_launching: Box<dyn FnOnce() -> ()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_finish_launching(&self, _: Box<dyn FnOnce() -> ()>) {}
|
||||
|
||||
fn dispatcher(&self) -> Arc<dyn super::Dispatcher> {
|
||||
self.dispatcher.clone()
|
||||
@@ -61,8 +59,7 @@ impl super::Platform for Platform {
|
||||
Ok(Box::new(Window::new(options.bounds.size())))
|
||||
}
|
||||
|
||||
fn set_menus(&self, _menus: &[crate::Menu]) {
|
||||
}
|
||||
fn set_menus(&self, _menus: &[crate::Menu]) {}
|
||||
|
||||
fn quit(&self) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user