Skip to main content

plugin_view/
plugin_view.rs

1use std::path::PathBuf;
2
3use maruzzella::{
4    default_product_spec, plugin_tab, run, ButtonAppearance, ButtonStyle, MaruzzellaConfig,
5    SurfaceAppearance, SurfaceLevel, TabGroupSpec, TabStripAppearance, TabStripStyle, TextRole,
6    ThemeSpec, Tone, WorkbenchNodeSpec,
7};
8
9fn main() {
10    let plugin_path = example_plugin_path();
11    if !plugin_path.exists() {
12        eprintln!(
13            "example plugin not found at {}\nbuild it first with: cargo build -p example_plugin",
14            plugin_path.display()
15        );
16        return;
17    }
18
19    let mut product = default_product_spec();
20    product.branding.title = "Plugin View Demo".to_string();
21    product.branding.search_placeholder = "Search plugin demo".to_string();
22    product.branding.status_text = "Plugin-backed GTK view with semantic shell styling".to_string();
23
24    product.layout.workbench = WorkbenchNodeSpec::Group(
25        TabGroupSpec::new(
26            "workbench-plugin-demo",
27            Some("plugin-welcome"),
28            vec![
29                plugin_tab(
30                    "plugin-welcome",
31                    "workbench-plugin-demo",
32                    "Plugin Welcome",
33                    "com.example.hello.welcome",
34                    "The example plugin view could not be created.",
35                    false,
36                ),
37                maruzzella::text_tab(
38                    "notes",
39                    "workbench-plugin-demo",
40                    "Notes",
41                    "This second tab remains host-owned placeholder content.",
42                    true,
43                ),
44            ],
45        )
46        .with_panel_appearance("demo-workbench")
47        .with_panel_header_appearance("demo-header")
48        .with_tab_strip_appearance("demo-tabs"),
49    );
50
51    let config = MaruzzellaConfig::new("com.example.maruzzella.plugin-view")
52        .with_persistence_id("plugin-view-demo")
53        .with_theme(plugin_demo_theme())
54        .with_product(product)
55        .with_plugin_path(plugin_path);
56
57    run(config);
58}
59
60fn example_plugin_path() -> PathBuf {
61    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
62    path.push("target");
63    path.push("debug");
64    path.push(format!(
65        "{}example_plugin{}",
66        std::env::consts::DLL_PREFIX,
67        std::env::consts::DLL_SUFFIX
68    ));
69    path
70}
71
72fn plugin_demo_theme() -> ThemeSpec {
73    let mut theme = ThemeSpec::default();
74    theme.typography.font_family = "\"Space Grotesk\", \"Noto Sans\", sans-serif".to_string();
75    theme.typography.mono_font_family = "\"JetBrains Mono\", monospace".to_string();
76    theme.palette.bg_0 = "#0f1318".to_string();
77    theme.palette.bg_1 = "#18202a".to_string();
78    theme.palette.workbench = "#0c1015".to_string();
79    theme.palette.panel_left = "#131920".to_string();
80    theme.palette.panel_right = "#131a22".to_string();
81    theme.palette.panel_bottom = "#0a0d12".to_string();
82    theme.palette.border = "#27303c".to_string();
83    theme.palette.border_strong = "#3d4959".to_string();
84    theme.palette.text_0 = "#e3edf7".to_string();
85    theme.palette.text_1 = "#acb9c8".to_string();
86    theme.palette.text_2 = "#738197".to_string();
87    theme.palette.accent = "#36c2a3".to_string();
88    theme.palette.accent_strong = "#72f0cf".to_string();
89    theme.density.radius_medium = 10;
90    theme.density.radius_large = 14;
91    theme.density.toolbar_height = 42;
92    theme.density.tab_height = 30;
93
94    theme
95        .with_surface_appearance(
96            "topbar",
97            SurfaceAppearance::new(Tone::Primary, SurfaceLevel::Flat, TextRole::BodyStrong),
98        )
99        .with_surface_appearance(
100            "toolbar",
101            SurfaceAppearance::new(Tone::Primary, SurfaceLevel::Raised, TextRole::Body),
102        )
103        .with_surface_appearance(
104            "demo-workbench",
105            SurfaceAppearance::new(Tone::Neutral, SurfaceLevel::Sunken, TextRole::Body)
106                .borderless(),
107        )
108        .with_surface_appearance(
109            "demo-header",
110            SurfaceAppearance::new(Tone::Secondary, SurfaceLevel::Flat, TextRole::SectionLabel),
111        )
112        .with_button_appearance(
113            "primary",
114            ButtonAppearance::new(Tone::Accent, ButtonStyle::Solid, TextRole::BodyStrong),
115        )
116        .with_button_appearance(
117            "ghost",
118            ButtonAppearance::new(Tone::Secondary, ButtonStyle::Ghost, TextRole::Body),
119        )
120        .with_tab_strip_appearance(
121            "demo-tabs",
122            TabStripAppearance::new(Tone::Secondary, TabStripStyle::Editor, TextRole::TabLabel),
123        )
124}