Last active
April 21, 2020 23:26
-
-
Save simlay/b4d60dfe96523f2741d3c2466d4cb44d to your computer and use it in GitHub Desktop.
EventHandler.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use winit::{ | |
event::{StartCause, Event, WindowEvent}, | |
event_loop::{ControlFlow, EventLoop}, | |
window::{ | |
WindowBuilder, | |
Window | |
}, | |
platform::ios::{ | |
WindowExtIOS, | |
EventLoopExtIOS, | |
WindowBuilderExtIOS, | |
}, | |
}; | |
use dispatch::{Queue}; | |
use std::{ | |
sync::{ | |
mpsc::{ | |
channel, | |
Sender, | |
}, | |
}, | |
}; | |
use uikit_sys::{ | |
self, | |
//UIView, | |
//UIViewController, | |
UIView_UIViewRendering, | |
UIView_UIViewHierarchy, | |
UIView_UIViewGeometry, | |
UISwitch, | |
IUISwitch, | |
UIView, | |
IUIView, | |
IUIColor, | |
UIColor, | |
CGRect, | |
CGPoint, | |
CGSize, | |
id, | |
}; | |
pub fn main() -> ! { | |
debug_init(); | |
log::debug!("STARTING THE APP!"); | |
let event_loop = EventLoop::new(); | |
let window : Window = WindowBuilder::new() | |
.with_title("UIKit Rust App") | |
.with_maximized(true) | |
.build(&event_loop) | |
.expect("Failed to build window"); | |
window.request_redraw(); | |
let (sender, receiver) = channel(); | |
event_loop.run(move |event: Event<()>, _, control_flow: &mut ControlFlow| { | |
//println!("{:?}", event); | |
*control_flow = ControlFlow::Wait; | |
match event { | |
Event::NewEvents(StartCause::Init) => { | |
let root_view: UIView = UIView(window.ui_view() as id ); | |
unsafe { | |
let color = UIColor::alloc(); | |
let background = UIColor(color.initWithRed_green_blue_alpha_(0.1, 1.0, 2.0, 2.0)); | |
root_view.setBackgroundColor_(background.0); | |
} | |
let root_view: UIView = UIView(window.ui_view() as id ); | |
add_views(root_view); | |
add_switch(root_view, sender.clone()); | |
} | |
Event::LoopDestroyed => return, | |
Event::RedrawRequested(_) => { | |
} | |
Event::WindowEvent { ref event, .. } => match event { | |
WindowEvent::Resized(_logical_size) => { | |
//window.request_redraw(); | |
} | |
WindowEvent::Touch(_touch) => { | |
}, | |
WindowEvent::CloseRequested => { | |
*control_flow = ControlFlow::Exit | |
} | |
_ => (), | |
}, | |
_ => (), | |
} | |
}) | |
} | |
fn add_views(root_view: UIView) { | |
add_rect(root_view); | |
add_input(root_view); | |
} | |
fn add_rect(root_view: UIView) { | |
let rect = CGRect { | |
origin: CGPoint { | |
x: 10.0, | |
y: 20.0 | |
}, | |
size: CGSize { | |
height: 20.0, | |
width: 20.0, | |
} | |
}; | |
unsafe { | |
let rect = { | |
let foo : UIView = UIView(UIView::alloc().initWithFrame_(rect)); | |
let yellow = UIColor(UIColor::yellowColor()); | |
foo.setBackgroundColor_(yellow.0); | |
foo.setUserInteractionEnabled_(true); | |
foo | |
}; | |
root_view.addSubview_(rect.0); | |
} | |
} | |
fn add_input(root_view: UIView) { | |
use uikit_sys::{ | |
UITextView, | |
IUITextView, | |
}; | |
let input_rect = CGRect { | |
origin: CGPoint { | |
x: 10.0, | |
y: 50.0 | |
}, | |
size: CGSize { | |
width: 200.0, | |
height: 200.0, | |
} | |
}; | |
unsafe { | |
let input = { | |
let foo = UITextView( | |
UITextView::alloc().initWithFrame_textContainer_( | |
input_rect, | |
0 as id, | |
) | |
); | |
foo | |
}; | |
root_view.addSubview_(input.0); | |
} | |
} | |
use objc::{ | |
declare::ClassDecl, | |
runtime::{ | |
Object, | |
Class, | |
Sel, | |
}, | |
}; | |
use core::ffi::c_void; | |
#[repr(transparent)] | |
struct EventHandler(pub id); | |
impl EventHandler { | |
fn new<F>(func: &mut F) -> Self | |
where F: FnMut() + Send + 'static | |
{ | |
let func = func as *mut F as *mut c_void; | |
let obj = unsafe { | |
let obj: id = msg_send![Self::class::<F>(), alloc]; | |
let obj: id = msg_send![obj, init]; | |
(*obj).set_ivar::<*mut c_void>("closure", func); | |
obj | |
}; | |
Self(obj) | |
} | |
extern fn event<F>(this: &Object, _cmd: Sel) | |
where F: FnMut() + Send + 'static | |
{ | |
unsafe { | |
let func = *this.get_ivar::<*mut c_void>("closure") as *mut F; | |
(*func)(); | |
} | |
} | |
fn class<F>() -> &'static Class | |
where F: FnMut() + Send + 'static | |
{ | |
let cls_name = "RustHandler"; | |
match Class::get(cls_name) { | |
Some(cls) => cls, | |
None => { | |
let superclass = class!(NSObject); | |
let mut decl = ClassDecl::new(cls_name, superclass).unwrap(); | |
unsafe { | |
decl.add_method( | |
sel!(sendEvent), | |
Self::event::<F> as extern "C" fn(&Object, Sel), | |
); | |
decl.add_ivar::<*mut c_void>( | |
"closure", | |
); | |
} | |
decl.register() | |
} | |
} | |
} | |
} | |
fn add_switch(root_view: UIView, _sender: Sender<i32>) { | |
use uikit_sys::IUIControl; | |
let mut foo : i32 = 0; | |
println!("THIS is foo = {:?}!", foo); | |
let toggle_handler = EventHandler::new(&mut move ||{ | |
println!("THIS IS THE PASSED IN CLOSURE! foo = {:?}!", foo); | |
foo += 1; | |
}); | |
unsafe { | |
let switch = UISwitch( | |
IUISwitch::initWithFrame_( | |
UISwitch::alloc(), | |
CGRect { | |
origin: CGPoint { | |
x: 10.0, | |
y: 250.0 | |
}, | |
size: CGSize { | |
height: 20.0, | |
width: 20.0, | |
} | |
} | |
) | |
); | |
switch.addTarget_action_forControlEvents_( | |
toggle_handler.0, | |
sel!(sendEvent), | |
uikit_sys::UIControlEvents_UIControlEventValueChanged, | |
); | |
root_view.addSubview_(switch.0); | |
} | |
} | |
fn debug_init() { | |
color_backtrace::install_with_settings( | |
color_backtrace::Settings::new().verbosity(color_backtrace::Verbosity::Full), | |
); | |
pretty_env_logger::init(); | |
std::env::set_var("RUST_LOG", "DEBUG"); | |
std::env::set_var("RUST_BACKTRACE", "full"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment