Created
September 23, 2024 14:40
-
-
Save 2tvenom/160e7d4e7b8e63dd83133067094197b6 to your computer and use it in GitHub Desktop.
This file contains 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
#![deny(unsafe_op_in_unsafe_fn)] | |
#![allow(clippy::incompatible_msrv)] | |
mod tut; | |
use std::cell::OnceCell; | |
use std::ffi::c_void; | |
use objc2::rc::{Id, Retained}; | |
use objc2::encode::{Encode, RefEncode}; | |
use objc2::runtime::{AnyObject, ProtocolObject}; | |
use objc2::{declare_class, msg_send_id, ClassType, mutability, DeclaredClass, Encoding, msg_send}; | |
use objc2_foundation::{NSObject, ns_string, NSString, NSRect, MainThreadMarker, NSObjectProtocol, | |
NSNotification, NSPoint, NSSize, NSInteger, NSArray, CGFloat, NSCoding}; | |
use objc2_app_kit::{NSApplicationActivationPolicy, NSApplication, NSScrollView, | |
NSControlTextEditingDelegate, NSTableColumn, NSTableView, NSWindow, | |
NSWindowStyleMask, NSApplicationDelegate, NSBackingStoreType, | |
NSTableViewDataSource, NSTableViewDelegate, NSView, NSTextField, NSStackView, | |
NSUserInterfaceLayoutOrientation, NSLayoutAttribute, NSColor, NSTableRowView}; | |
declare_class!( | |
struct TableViewSource; | |
unsafe impl ClassType for TableViewSource { | |
type Super = NSObject; | |
type Mutability = mutability::MainThreadOnly; | |
const NAME: &'static str = "TableViewSource"; | |
} | |
impl DeclaredClass for TableViewSource { | |
// type Ivars = Ivars; | |
} | |
unsafe impl NSObjectProtocol for TableViewSource {} | |
unsafe impl NSControlTextEditingDelegate for TableViewSource {} | |
// unsafe impl NSCoding for TableViewSource {} | |
unsafe impl NSTableViewDelegate for TableViewSource { | |
#[method(tableView:heightOfRow:)] | |
unsafe fn table_view_height_of_row(&self, _: &NSTableView, _: NSInteger) -> CGFloat { | |
30. | |
} | |
#[method_id(tableView:rowViewForRow:)] | |
unsafe fn tableView_rowViewForRow( | |
&self, | |
table_view: &NSTableView, | |
row: NSInteger, | |
) -> Option<Retained<NSTableRowView>> { | |
println!("row view for {}", row); | |
None | |
} | |
#[method(tableView:didAddRowView:forRow:)] | |
unsafe fn table_view_did_add_row_view_for_row( | |
&self, | |
_: &NSTableView, | |
_: &NSTableRowView, | |
_: NSInteger, | |
) { | |
println!("tableView_didAddRowView:forRow:"); | |
} | |
#[method(tableView:willDisplayCell:forTableColumn:row:)] | |
unsafe fn table_view_will_display_cell_for_table_column_row( | |
&self, | |
table_view: &NSTableView, | |
cell: &AnyObject, | |
table_column: Option<&NSTableColumn>, | |
row: NSInteger, | |
) { | |
println!("tableView_willDisplayCell:forTableColumn:row:"); | |
} | |
#[method_id(tableView:viewForTableColumn:row:)] | |
unsafe fn tableView_viewForTableColumn_row( | |
&self, | |
_: &NSTableView, | |
_: Option<&NSTableColumn>, | |
_: NSInteger, | |
) -> Option<Retained<NSView>> { | |
println!("tableView_forTableColumn:row:"); | |
// None | |
let mtm = MainThreadMarker::from(self); | |
let view = unsafe { | |
NSView::initWithFrame( | |
mtm.alloc(), | |
NSRect::new(NSPoint::new(0.0, 0.0), NSSize::new(40.0, 40.0)), | |
) | |
}; | |
unsafe { | |
view.setWantsLayer(true); | |
#[repr(transparent)] | |
struct CGColorRef(*mut c_void); | |
unsafe impl Encode for CGColorRef { | |
const ENCODING: Encoding = Encoding::Pointer(&Encoding::Struct("CGColor", &[])); | |
} | |
let background = NSColor::redColor() ; | |
let background: CGColorRef = msg_send![&background, CGColor]; | |
// CALayer | |
let layer: Id<NSObject> = msg_send_id![&view, layer]; | |
let _: () = msg_send![&layer, setBorderWidth: 2.0 as CGFloat]; | |
let _: () = msg_send![&layer, setBorderColor: background]; | |
} | |
let label = unsafe { | |
let l = NSTextField::init(mtm.alloc()); | |
l.setSelectable(false); | |
l.setWantsLayer(true); | |
l.setTranslatesAutoresizingMaskIntoConstraints(false); | |
l.setStringValue(ns_string!("dummy")); | |
l.setTextColor(Some(NSColor::redColor().as_ref())); | |
l | |
}; | |
let views = [ | |
Id::into_super(Id::into_super(label)) | |
]; | |
let stack = unsafe{ | |
let s = NSStackView::stackViewWithViews(&NSArray::from_id_slice(&views),mtm); | |
s.setOrientation(NSUserInterfaceLayoutOrientation::Vertical); | |
s.setAlignment(NSLayoutAttribute::CenterX); | |
s.setSpacing(8.0); | |
s.setTranslatesAutoresizingMaskIntoConstraints(false); | |
s | |
}; | |
unsafe { | |
view.addSubview(&stack); | |
} | |
Some(view) | |
} | |
} | |
); | |
declare_class!( | |
struct TableDataSource; | |
unsafe impl ClassType for TableDataSource { | |
type Super = NSObject; | |
type Mutability = mutability::MainThreadOnly; | |
const NAME: &'static str = "TableDataSource"; | |
} | |
impl DeclaredClass for TableDataSource { | |
// type Ivars = Ivars; | |
} | |
unsafe impl NSObjectProtocol for TableDataSource {} | |
unsafe impl NSTableViewDataSource for TableDataSource { | |
#[method(numberOfRowsInTableView:)] | |
unsafe fn number_of_rows_in_table_view(&self, _: &NSTableView) -> NSInteger { | |
2 | |
} | |
} | |
); | |
#[derive(Debug)] | |
#[allow(unused)] | |
struct Ivars { | |
window: OnceCell<Retained<NSWindow>>, | |
} | |
declare_class!( | |
struct AppDelegate; | |
unsafe impl ClassType for AppDelegate { | |
type Super = NSObject; | |
type Mutability = mutability::MainThreadOnly; | |
const NAME: &'static str = "AppDelegate"; | |
} | |
impl DeclaredClass for AppDelegate { | |
type Ivars = Ivars; | |
} | |
unsafe impl NSObjectProtocol for AppDelegate {} | |
unsafe impl NSApplicationDelegate for AppDelegate { | |
#[method(applicationDidFinishLaunching:)] | |
fn application_did_finish_launching(&self, _notification: &NSNotification) { | |
let mtm = MainThreadMarker::from(self); | |
// create the app window | |
self.new_window(mtm) | |
} | |
#[method(applicationWillTerminate:)] | |
fn will_terminate(&self, _notification: &NSNotification) { | |
println!("It's a hell of a start, it could be made into a monster\nIf we all pull together as a team"); | |
} | |
#[method(applicationShouldTerminateAfterLastWindowClosed:)] | |
fn application_should_terminate_after_last_window_closed(&self, _: &NSApplication)->bool { | |
true | |
} | |
} | |
); | |
impl TableDataSource { | |
fn new(mtm: MainThreadMarker) -> Retained<Self> { | |
let this = mtm.alloc(); | |
unsafe { msg_send_id![this, init] } | |
} | |
} | |
impl TableViewSource { | |
fn new(mtm: MainThreadMarker) -> Retained<Self> { | |
let this = mtm.alloc(); | |
unsafe { msg_send_id![this, init] } | |
} | |
} | |
impl AppDelegate { | |
fn new(mtm: MainThreadMarker) -> Retained<Self> { | |
let this = mtm.alloc(); | |
let this = this.set_ivars(Ivars { | |
window: OnceCell::default(), | |
}); | |
unsafe { msg_send_id![super(this), init] } | |
} | |
fn new_window(&self, mtm: MainThreadMarker) { | |
let this = mtm.alloc(); | |
let window = { | |
let content_rect = NSRect::new(NSPoint::new(0., 0.), NSSize::new(768., 768.)); | |
let style = NSWindowStyleMask::Closable | |
| NSWindowStyleMask::Resizable | |
| NSWindowStyleMask::Titled | |
| NSWindowStyleMask::Miniaturizable | |
| NSWindowStyleMask::UnifiedTitleAndToolbar | |
| NSWindowStyleMask::UnifiedTitleAndToolbar | |
; | |
let backing_store_type = NSBackingStoreType::NSBackingStoreBuffered; | |
let flag = false; | |
unsafe { | |
NSWindow::initWithContentRect_styleMask_backing_defer( | |
this, | |
content_rect, | |
style, | |
backing_store_type, | |
flag, | |
) | |
} | |
}; | |
// window.makeKeyAndOrderFront(None); | |
unsafe { | |
window.orderFrontRegardless(); | |
} | |
window.setTitle(&NSString::from_str("Rust NSTableView Example")); | |
window.center(); | |
let column = { | |
unsafe { | |
let c = NSTableColumn::initWithIdentifier(mtm.alloc(), ns_string!("dummy")); | |
// c.setWidth(300.); | |
c.setTitle(ns_string!("dummy")); | |
c | |
} | |
}; | |
let column1 = { | |
unsafe { | |
let c = NSTableColumn::init(mtm.alloc()); | |
// c.setWidth(300.); | |
c.setTitle(ns_string!("dummy1")); | |
c | |
} | |
}; | |
// Set up the data source and delegate | |
// let data_source = Box::new(TableDataSource::new()); | |
// let delegate = Box::new(TableDataSource::new()); | |
let ts = TableDataSource::new(mtm); | |
let ts_obj = ProtocolObject::from_ref(&*ts); | |
let tv = TableViewSource::new(mtm); | |
let tv_obj = ProtocolObject::from_ref(&*tv); | |
let table = { | |
let content_rect = NSRect::new(NSPoint::new(0., 0.), NSSize::new(100., 100.)); | |
unsafe { | |
let t = NSTableView::initWithFrame(mtm.alloc(), content_rect); | |
t.addTableColumn(&column); | |
t.addTableColumn(&column1); | |
t.setDataSource(Some(ts_obj)); | |
t.setDelegate(Some(tv_obj)); | |
t | |
} | |
}; | |
let sc = { | |
// let content_rect = NSRect::new(NSPoint::new(0., 0.), NSSize::new(100., 100.)); | |
unsafe { | |
let scroll_view = NSScrollView::new(mtm); | |
scroll_view.setDocumentView(Some(&table)); | |
scroll_view | |
} | |
}; | |
// unsafe { | |
window.setContentView(Some(&sc)); | |
// } | |
self.ivars().window.set(window).expect("error set window"); | |
} | |
} | |
fn main() { | |
let mtm: MainThreadMarker = MainThreadMarker::new().unwrap(); | |
let app = NSApplication::sharedApplication(mtm); | |
app.setActivationPolicy(NSApplicationActivationPolicy::Regular); | |
// configure the application delegate | |
let delegate = AppDelegate::new(mtm); | |
let object = ProtocolObject::from_ref(&*delegate); | |
app.setDelegate(Some(object)); | |
// run the app | |
unsafe { | |
app.run(); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment