← luna

Commit 3a3cdab

4
files
+98
added
-6
deleted
@@ -269,10 +269,11 @@ cargo run -p luna-demo --bin render -- --theme examples/luna/themes/nord.theme d
269 269 cargo run -p luna-demo --bin layout -- --theme examples/luna/themes/nord.theme --out docs/images/layout-nord.png
270 270 ```
271 271
272 -Do zrobienia pozostaje **okno podglądu na żywo** przy wyborze (miniatura). Sam wybór stylu
273 -działa już w demo: **menu `☰` → „Styl”** otwiera listę („Domyślny” + style z plików),
274 -a wybór jest natychmiast stosowany i zapisywany w `theme.conf`. W headless demo/testach katalog
275 -ze stylami wskazuje `LUNA_THEMES_DIR`.
272 +Do zrobienia pozostaje **okno podglądu na żywo** wewnątrz aplikacji (miniatura aktualizowana przy
273 +przewijaniu listy). Sam wybór stylu działa już w demo: **menu `☰` → „Styl”** otwiera listę
274 +(„Domyślny” + style z plików), a wybór jest natychmiast stosowany i zapisywany w `theme.conf`.
275 +Headlessowy podgląd (montaż motywów) to `cargo run -p luna-demo --bin styles` →
276 +`docs/images/styles.png`. W headless demo/testach katalog ze stylami wskazuje `LUNA_THEMES_DIR`.
276 277
277 278 ### Co jeszcze decyduje o „looku GTK4”
278 279
@@ -384,6 +385,11 @@ Style instalowane z plików (`examples/luna/themes/nord.theme`, `paper.theme`)
384 385 ![Ustawienia — styl Nord](docs/images/settings-nord.png)
385 386 ![Ustawienia — styl Paper](docs/images/settings-paper.png)
386 387
388 +Podgląd kilku motywów (headless, `cargo run -p luna-demo --bin styles`) — ten sam realny
389 +interfejs w każdym stylu:
390 +
391 +![Podgląd stylów](docs/images/styles.png)
392 +
387 393 Przebieg interakcji (headless `simulate`) — m.in. menu `☰`, dolny panel, powiadomienie (`Toast`)
388 394 karta 12 i ekran stanu („Brak wyników”) klatka 14:
389 395
390 396 new file mode 100644
@@ -0,0 +1,84 @@
1 +//! Podgląd stylów — renderuje ten sam (realny) interfejs w kilku motywach i składa
2 +//! montaż. Headlessowy odpowiednik „okna podglądu” przy wyborze stylu.
3 +//!
4 +//! Uruchom: `cargo run -p luna-demo --bin styles`
5 +//! Efekt: `docs/images/styles.png`
6 +
7 +use std::error::Error;
8 +use std::path::Path;
9 +
10 +use libluna_core::{Accent, Size, ThemePreference};
11 +use libluna_render::{Scene, SoftwareRenderer, TextEngine};
12 +use luna_demo::ui::{self, Demo};
13 +use tiny_skia::{FilterQuality, IntSize, Pixmap, PixmapPaint, Transform};
14 +
15 +const W: u32 = 900;
16 +const H: u32 = 1028;
17 +const COLS: u32 = 2;
18 +
19 +/// (etykieta, preferencja, ścieżka stylu) — kolejność = kolejność kafli.
20 +fn specs<'a>() -> [(&'a str, ThemePreference, Option<&'a str>); 4] {
21 + [
22 + ("Luna Light", ThemePreference::Light, None),
23 + ("Luna Dark", ThemePreference::Dark, None),
24 + ("Nord", ThemePreference::Dark, Some("nord.theme")),
25 + ("Paper", ThemePreference::Light, Some("paper.theme")),
26 + ]
27 +}
28 +
29 +fn themes_dir() -> std::path::PathBuf {
30 + Path::new(env!("CARGO_MANIFEST_DIR")).join("../../examples/luna/themes")
31 +}
32 +
33 +fn main() -> Result<(), Box<dyn Error>> {
34 + let text = TextEngine::system();
35 + let size = Size::new(W as f64, H as f64);
36 + let dir = themes_dir();
37 +
38 + // Kafle: render interfejsu w danym motywie.
39 + let mut tiles: Vec<Vec<u8>> = Vec::new();
40 + for (label, pref, style) in specs() {
41 + let mut theme = pref.resolve(false, Accent::Blue);
42 + if let Some(file) = style {
43 + match libluna_core::theme_file::load_spec(&dir.join(file).to_string_lossy()) {
44 + Some(patch) => theme = patch.build(theme),
45 + None => eprintln!("{label}: style not found: {file}"),
46 + }
47 + }
48 + let mut scene = Scene::new();
49 + ui::build_scene(
50 + &mut scene,
51 + &theme,
52 + &text,
53 + size,
54 + &Demo::default(),
55 + pref,
56 + Accent::Blue,
57 + );
58 + let mut renderer = SoftwareRenderer::new(W, H);
59 + renderer.draw(&scene, 1.0, theme.colors.window_bg);
60 + tiles.push(renderer.data().to_vec());
61 + }
62 +
63 + // Montaż `COLS` x `rows` (skalowanie + przesunięcie w jednej transformacji).
64 + let rows = (tiles.len() as u32).div_ceil(COLS);
65 + let cell_w = W / COLS;
66 + let cell_h = (H as f64 * cell_w as f64 / W as f64).round() as u32;
67 + let mut montage = Pixmap::new(cell_w * COLS, cell_h * rows).unwrap();
68 + let paint = PixmapPaint {
69 + quality: FilterQuality::Bilinear,
70 + ..Default::default()
71 + };
72 + for (i, pixels) in tiles.iter().enumerate() {
73 + let src = Pixmap::from_vec(pixels.clone(), IntSize::from_wh(W, H).unwrap()).unwrap();
74 + let t = Transform::from_scale(cell_w as f32 / W as f32, cell_h as f32 / H as f32)
75 + .post_translate(
76 + (i as u32 % COLS) as f32 * cell_w as f32,
77 + (i as u32 / COLS) as f32 * cell_h as f32,
78 + );
79 + montage.draw_pixmap(0, 0, src.as_ref(), &paint, t, None);
80 + }
81 + montage.save_png("docs/images/styles.png")?;
82 + println!("saved docs/images/styles.png ({} styles)", tiles.len());
83 + Ok(())
84 +}
0 85 new file mode 100644
1 86 Binary files /dev/null and b/docs/images/styles.png differ
@@ -57,8 +57,10 @@ a na końcu odtworzył realne aplikacje środowiska Luna z makiet.
57 57 przykłady `examples/luna/themes/*.theme`, podgląd przez `render/layout --theme`.
58 58 - Wybór stylu w UI: menu `☰` → „Styl” (lista `available_themes()`, „Domyślny” + style z plików),
59 59 stosowany na żywo i zapisywany w `theme.conf`; `LUNA_THEMES_DIR` dla dev/testów.
60 -- Dalej: **okno podglądu** przy wyborze (miniatura z realnych widgetów), scroll/overflow
61 - w `TabBar`, migracja `luna-demo` na drzewo układu.
60 +- Podgląd motywów (headless): `bin/styles` renderuje realny interfejs w kilku stylach i składa
61 + montaż (`docs/images/styles.png`) — odpowiednik „okna podglądu”.
62 +- Dalej: **okno podglądu na żywo w aplikacji**, scroll/overflow w `TabBar`,
63 + migracja `luna-demo` na drzewo układu.
62 64
63 65 ## M2 — Układ + widgety bazowe
64 66 - Dwuprzebiegowy silnik measure/allocate — ✅ **częściowo** (silnik + kontenery `VBox`/`HBox`,