ferroui_diagnostics/diagnostics/views/
main_view.rs1use crate::diagnostics::view_models::MainViewModel;
6use ferroui_base::controls::NameScopeExtensions;
7use ferroui_base::input::InputElementImpl;
8use ferroui_base::interactivity::InteractiveImpl;
9use ferroui_base::layout::LayoutableImpl;
10use ferroui_base::metadata::{from_markup_value, into_markup_value};
11use ferroui_base::{
12 ferro_class, ferro_class_info, ferro_impl_classes, instantiate, FerroObjectImpl, Ref,
13 StyledElementImpl, StyledElementImplExt, VisualImpl,
14};
15use ferroui_markup::data::Binding;
16use ferroui_controls::primitives::TemplatedControlImpl;
17use ferroui_controls::{ContentControl, TabControl, TabItem};
18use ferroui_controls::{ContentControlImpl, Control, ControlImpl, UserControl};
19use std::cell::RefCell;
20use std::rc::Rc;
21
22#[repr(C)]
25pub struct MainView {
26 base: UserControl,
27 extension_tabs: RefCell<Vec<Ref<TabItem>>>,
30}
31
32ferro_class!(MainView: UserControl);
33ferro_impl_classes!(
34 MainView: FerroObjectImpl,
35 VisualImpl,
36 LayoutableImpl,
37 InteractiveImpl,
38 InputElementImpl,
39 ControlImpl,
40 TemplatedControlImpl,
41 ContentControlImpl
42);
43ferro_class_info!(MainView { new: MainView::new });
44
45impl StyledElementImpl for MainView {
46 fn on_data_context_changed(this: &Self) {
49 Self::parent_on_data_context_changed(this);
50 this.update_extension_tabs();
51 }
52}
53
54impl MainView {
55 pub const DOCUMENT_URI: &'static str = "ferres://FerroUI.Diagnostics/diagnostics/views/MainView.xaml";
57
58 pub fn construct() -> Self {
59 Self { base: UserControl::construct(), extension_tabs: RefCell::new(Vec::new()) }
60 }
61
62 pub fn new() -> Ref<Self> {
70 crate::register_types();
71 let this = instantiate(Self::construct());
72 Self::initialize_component(&this);
73 this
74 }
75
76 fn initialize_component(this: &Ref<Self>) {
78 if let Err(error) = crate::compiled_diagnostics_views_main_view::populate(None, this) {
79 panic!("{}: {error}", Self::DOCUMENT_URI);
80 }
81 }
82
83 fn update_extension_tabs(&self) {
88 let Some(tab_control) = NameScopeExtensions::find_name_scope(self)
89 .and_then(|name_scope| name_scope.find_as::<TabControl>("tabControl"))
90 else {
91 return;
93 };
94 let items = tab_control.items();
95
96 let old_tabs: Vec<Ref<TabItem>> = self.extension_tabs.borrow_mut().drain(..).collect();
97 for tab in old_tabs {
98 items.remove(&Some(Control::boxed(tab)));
99 }
100
101 let Some(view_model) = from_markup_value::<Rc<MainViewModel>>(&self.data_context()) else {
102 return;
103 };
104
105 let mut tabs = Vec::new();
106 for page in view_model.extension_pages() {
107 let tab = TabItem::new();
108 tab.set_header(into_markup_value(page.title().to_string()));
109 let _ = tab.bind_binding(ContentControl::content_property().as_property(), &*Binding::with_path("Content"));
111 items.add(Some(Control::boxed(tab.clone())));
112 tabs.push(tab);
113 }
114 *self.extension_tabs.borrow_mut() = tabs;
115 }
116}