SplitViewController doesn't implement Layout (or super-trait ObjcAccess) - example code?
Closed this issue · 4 comments
I'm impressed with what I've been able to do with cacao
, thank you for the hard work you've put into this:
I'm trying to scaffold an app with the SplitViewController
three column setup as a candidate for using this for one of our internal apps, and have gotten stuck on instantiating a SuperViewController
in a simple test app.
If there is an example of a SplitViewController
being instantiated and presented in a cacao
example (or other) app. I've searched thoroughly, to no avail, but would be happy to get a referral and if it is working, I'll thank you and consider this closed and will focus on analyzing what the example did that I'm missing.
Without an example, though, here is what I tried:
mod views;
use cacao::appkit::{App, AppDelegate};
use cacao::button::Button;
use cacao::appkit::window::{Window, WindowConfig, WindowStyle};
use cacao::geometry::Rect;
use cacao::appkit::window::WindowToolbarStyle;
use cacao::foundation::NSUInteger;
use cacao::view::{SplitViewController, View};
use crate::views::sidebar_view::SidebarView;
use crate::views::content_view::ContentView;
use crate::views::detail_view::DetailView;
struct CacaoTest2 {
window: Window,
}
impl AppDelegate for CacaoTest2 {
fn did_finish_launching(&self) {
self.window.show();
}
}
fn main() {
let button = Button::new("Click me!");
// let main_view = MainView::default();
let window_config = WindowConfig {
style: (WindowStyle::Titled as NSUInteger
| WindowStyle::Closable as NSUInteger
| WindowStyle::Resizable as NSUInteger) as NSUInteger,
initial_dimensions: Rect::new(0.0, 0.0, 800.0, 600.0),
defer: false,
toolbar_style: WindowToolbarStyle::Automatic,
};
let window = Window::new(window_config);
let split_view_controller = SplitViewController::new(SidebarView::default(),
ContentView::default(),
Some(DetailView::default()));
window.set_content_view(&split_view_controller);
App::new("net.xdix.cacao_test_2", CacaoTest2 { window }).run();
}
I have the SidebarView
, ContentView
and DetailView
views defined and usable as simple (just a Label) views that work on their own just fine.
I've tried embedding the SplitControllerView
in an enclosing MainView
, and calling add_subview(splitViewController)
in the did_load()
override for that MainView
-- same error:
error[E0277]: the trait bound `SplitViewController<SidebarView, ContentView, DetailView>: cacao::layout::Layout` is not satisfied
--> src/main.rs:25:36
|
25 | self.window.set_content_view(&split_view_controller);
| ---------------- ^^^^^^^^^^^^^^^^^^^^^^ the trait `cacao::layout::Layout` is not implemented for `SplitViewController<SidebarView, ContentView, DetailView>`
| |
| required by a bound introduced by this call
I can upload a zip of the entire (small) project if it helps, but I'm guessing I just have a conceptual problem here in terms of the specific recipe needed for getting a SplitViewController working.
It's been a minute since I've touched that, but at a glance - you want window.set_content_view_controller
, not window.set_content_view
.
If that doesn't work, let me know and we can debug further. :)
It's been a minute since I've touched that, but at a glance - you want
window.set_content_view_controller
, notwindow.set_content_view
.If that doesn't work, let me know and we can debug further. :)
Thank you, will try that!
It's been a minute since I've touched that, but at a glance - you want
window.set_content_view_controller
, notwindow.set_content_view
.If that doesn't work, let me know and we can debug further. :)
That worked, thanks for the tip. Actually, it wasn't just window.set_content_view_controller()
, got a hang when just had it inserted after the window creation in main()
.
What made it work is creating a WindowDelegate
and using did_load()
to crate the SplitViewController
. Here's the WindowDelegate
and the main
sources for any who may want to see how it works:
main.rs
mod main_window;
use cacao::appkit::{App, AppDelegate};
use cacao::appkit::window::{Window, WindowConfig, WindowController, WindowStyle};
use crate::main_window::MainWindow;
struct MyApp {
window: WindowController<MainWindow>,
}
impl AppDelegate for MyApp {
fn did_finish_launching(&self) {
App::activate();
self.window.show();
}
fn should_terminate_after_last_window_closed(&self) -> bool {
true
}
}
fn main() {
App::new("net.groupmg.cacao-test", MyApp {
window: WindowController::with(WindowConfig::default(), MainWindow::default())
})
.run();
}
main_window.rs
use cacao::appkit::window::{Window, WindowDelegate};
use cacao::view::SplitViewController;
use crate::views::content_view::ContentView;
use crate::views::detail_view::DetailView;
use crate::views::sidebar_view::SidebarView;
#[derive(Default)]
pub struct MainWindow {
controller: Option<SplitViewController<SidebarView, ContentView, DetailView>>
}
impl WindowDelegate for MainWindow {
const NAME: &'static str = "MainWindow";
fn did_load(&mut self, window: Window) {
window.set_minimum_content_size(400., 400.);
window.set_title("MyApp");
let sidebar = SidebarView::default();
let content = ContentView::default();
let detail = DetailView::default();
let split_view_controller = SplitViewController::new(sidebar, content, Some(detail));
window.set_content_view_controller(&split_view_controller);
self.controller = Some(split_view_controller);
}
fn will_close(&self) {
println!("Closing now!");
}
}
Your comment was all I needed to get pointed in the right direction. Much appreciated!
Ah yeah - you def want to be creating things after did_finish_launching
since that ensures all the macOS-isms are set up in the background. :)
Glad it works! Should probably add an example to the repo at some point... closing this now but feel free to reopen if you hit further issues.