Skip to content

Instantly share code, notes, and snippets.

@2tvenom
Created October 28, 2024 19:34
Show Gist options
  • Save 2tvenom/05c868e506a80696cc4bef7005c02453 to your computer and use it in GitHub Desktop.
Save 2tvenom/05c868e506a80696cc4bef7005c02453 to your computer and use it in GitHub Desktop.
use crate::outline::{data_source::OutlineViewDataSource, delegate::OutlineViewDelegate};
use crate::AppDelegate;
use objc2::__framework_prelude::ProtocolObject;
use objc2::rc::{Retained, Weak};
use objc2::{declare_class, msg_send_id, sel, ClassType, DeclaredClass, MainThreadOnly};
use objc2_app_kit::{
NSButton, NSColor, NSOutlineView, NSScrollView, NSSplitViewController, NSSplitViewItem,
NSViewController,
};
use objc2_foundation::{ns_string, MainThreadMarker, NSObjectProtocol};
use std::cell::OnceCell;
use std::ops::Deref;
#[derive(Debug)]
pub struct SplitViewIvars {
app_delegate: OnceCell<Retained<AppDelegate>>,
outline_view_data_source: OnceCell<Retained<OutlineViewDataSource>>,
outline_view_delegate: OnceCell<Retained<OutlineViewDelegate>>,
}
declare_class!(
#[derive(Debug)]
pub struct SplitViewController;
unsafe impl ClassType for SplitViewController {
type Super = NSViewController;
const NAME: &'static str = "SecondViewController";
}
impl DeclaredClass for SplitViewController {
type Ivars = SplitViewIvars;
}
unsafe impl NSObjectProtocol for SplitViewController {}
unsafe impl SplitViewController {
#[method(loadView)]
fn load_view(&self) {
let mtm = MainThreadMarker::from(self);
self._load_view(mtm)
}
}
);
impl SplitViewController {
pub fn new(mtm: MainThreadMarker, app: Retained<AppDelegate>) -> Retained<Self> {
let this = mtm.alloc();
let app_once: OnceCell<Retained<AppDelegate>> = OnceCell::new();
app_once.set(app).expect("app already initialized");
let this = this.set_ivars(SplitViewIvars {
app_delegate: app_once,
outline_view_data_source: OnceCell::default(),
outline_view_delegate: OnceCell::default(),
});
unsafe { msg_send_id![super(this), init] }
}
fn _load_view(&self, mtm: MainThreadMarker) {
let color = unsafe {
NSColor::colorWithDisplayP3Red_green_blue_alpha(31. / 255., 33. / 255., 35. / 255., 1.)
};
let data_source = OutlineViewDataSource::new(mtm);
self.ivars()
.outline_view_data_source
.set(data_source.clone())
.expect("error set outline datasource");
let data_source_obj = ProtocolObject::from_ref(data_source.deref());
let delegate = OutlineViewDelegate::new(mtm);
self.ivars()
.outline_view_delegate
.set(delegate.clone())
.expect("error set outline delegate");
let delegate_obj = ProtocolObject::from_ref(delegate.deref());
let ov = unsafe {
let ov = NSOutlineView::init(mtm.alloc());
ov.setBackgroundColor(&color);
ov.setHeaderView(None);
ov.setDataSource(Some(data_source_obj));
ov.setDelegate(Some(delegate_obj));
ov
};
let sc = unsafe {
let scroll = NSScrollView::init(mtm.alloc());
scroll.setDocumentView(Some(&ov));
scroll.setBackgroundColor(&color);
scroll
};
let sidebar = unsafe {
let vc = NSViewController::init(mtm.alloc());
vc.setView(&sc);
let s = NSSplitViewItem::init(mtm.alloc());
s.setAllowsFullHeightLayout(true);
s.setMinimumThickness(100.);
s.setMaximumThickness(200.);
s.setCanCollapse(true);
s.setViewController(&vc);
s
};
let detail = unsafe {
let v = NSScrollView::new(mtm);
v.setBackgroundColor(&color);
let b1 = NSButton::buttonWithTitle_target_action(
ns_string!("second view button 1"),
Some(self.ivars().app_delegate.get().unwrap()),
Some(sel!(action1:)),
mtm,
);
v.addSubview(&b1);
let vc = NSViewController::init(mtm.alloc());
vc.setView(&v);
let detail = NSSplitViewItem::init(mtm.alloc());
detail.setViewController(&vc);
detail.setAllowsFullHeightLayout(true);
detail
};
let split = unsafe {
let s = NSSplitViewController::init(mtm.alloc());
s.view().setWantsLayer(true);
s.addSplitViewItem(&sidebar);
s.addSplitViewItem(&detail);
s
};
unsafe { self.setView(&split.view()) }
}
}
use objc2::rc::Retained;
use objc2::runtime::{AnyObject, NSObject, NSObjectProtocol};
use objc2::{class, declare_class, msg_send_id, ClassType, DeclaredClass, MainThreadOnly};
use objc2_app_kit::{NSOutlineView, NSOutlineViewDataSource, NSTableColumn};
use objc2_foundation::{MainThreadMarker, NSInteger, NSString};
declare_class!(
#[derive(Debug)]
pub struct OutlineViewDataSource;
unsafe impl ClassType for OutlineViewDataSource {
type Super = NSObject;
type ThreadKind = dyn MainThreadOnly;
const NAME: &'static str = "OutlineViewDataSource";
}
impl DeclaredClass for OutlineViewDataSource {}
unsafe impl NSObjectProtocol for OutlineViewDataSource {}
unsafe impl NSOutlineViewDataSource for OutlineViewDataSource {
#[method(outlineView:numberOfChildrenOfItem:)]
unsafe fn outline_view_number_of_children_of_item(
&self,
_: &NSOutlineView,
item: Option<&AnyObject>,
) -> NSInteger {
if let Some(item) = item {
0
} else {
5
}
}
#[method_id(outlineView:child:ofItem:)]
unsafe fn outline_view_child_of_item(
&self,
_: &NSOutlineView,
_: NSInteger,
item: Option<&AnyObject>,
) -> Retained<AnyObject> {
let key: Retained<AnyObject> = unsafe { msg_send_id![class!(NSString), new] };
key
}
#[method(outlineView:isItemExpandable:)]
unsafe fn outline_view_is_item_expandable(
&self,
_: &NSOutlineView,
item: &AnyObject,
) -> bool {
false
}
#[method_id(outlineView:objectValueForTableColumn:byItem:)]
unsafe fn outline_view_object_value_for_table_column_by_item(
&self,
outline_view: &NSOutlineView,
table_column: Option<&NSTableColumn>,
item: Option<&AnyObject>,
) -> Option<Retained<AnyObject>> {
let key: Retained<AnyObject> = unsafe { msg_send_id![class!(NSString), new] };
Some(key)
}
}
);
impl OutlineViewDataSource {
pub fn new(mtm: MainThreadMarker) -> Retained<Self> {
let this = mtm.alloc();
unsafe { msg_send_id![this, init] }
}
}
use std::ops::Deref;
use objc2::rc::{Retained, Weak};
use objc2::runtime::{AnyObject, NSObject, NSObjectProtocol};
use objc2::{declare_class, msg_send_id, ClassType, DeclaredClass, MainThreadOnly, Message};
use objc2_app_kit::{NSCell, NSControlTextEditingDelegate, NSOutlineView, NSOutlineViewDelegate, NSTableCellView, NSTableColumn, NSTextField, NSView};
use objc2_foundation::{ns_string, CGFloat, MainThreadMarker, NSString};
use crate::outline::item::OutlineItem;
declare_class!(
#[derive(Debug)]
pub struct OutlineViewDelegate;
unsafe impl ClassType for OutlineViewDelegate {
type Super = NSObject;
type ThreadKind = dyn MainThreadOnly;
const NAME: &'static str = "OutlineViewDelegate";
}
impl DeclaredClass for OutlineViewDelegate {}
unsafe impl NSObjectProtocol for OutlineViewDelegate {}
unsafe impl NSControlTextEditingDelegate for OutlineViewDelegate {}
unsafe impl NSOutlineViewDelegate for OutlineViewDelegate {
#[method(outlineView:heightOfRowByItem:)]
unsafe fn outline_view_height_of_row_by_item(
&self,
_: &NSOutlineView,
item: &AnyObject,
) -> CGFloat {
println!("outline_view_height_of_row_by_item:");
30.
}
#[method_id(outlineView:viewForTableColumn:item:)]
unsafe fn outline_view_view_for_table_column_item(
&self,
a: &NSOutlineView,
b: Option<&NSTableColumn>,
o: &AnyObject,
) -> Option<Retained<NSView>> {
println!("outline_view: ");
unsafe {
let t = NSTextField::new(MainThreadMarker::from(self));
t.setStringValue(ns_string!("dummy"));
t.sizeToFit();
let cell = NSTableCellView::new(MainThreadMarker::from(self));
cell.setTextField(Some(&t));
cell.superview()
}
}
}
);
impl OutlineViewDelegate {
pub fn new(mtm: MainThreadMarker) -> Retained<Self> {
let this = mtm.alloc();
unsafe { msg_send_id![this, init] }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment