← luna

Commit 797a833

7
files
+74
added
-74
deleted
@@ -100,10 +100,10 @@ fn main() -> Result<(), Box<dyn Error>> {
100 100 let mut renderer = SoftwareRenderer::new(w, h);
101 101 renderer.draw(&scene, 1.0, theme.colors.window_bg);
102 102
103 - let png = renderer.encode_png().ok_or("nie udało się zakodować PNG")?;
103 + let png = renderer.encode_png().ok_or("failed to encode PNG")?;
104 104 std::fs::write(&out, png)?;
105 105 println!(
106 - "zapisano {out} ({w}x{h}, lang={lang}, accent={})",
106 + "saved {out} ({w}x{h}, lang={lang}, accent={})",
107 107 accent.name()
108 108 );
109 109 Ok(())
@@ -66,7 +66,7 @@ fn main() -> Result<(), Box<dyn Error>> {
66 66
67 67 // 1. Start.
68 68 frames.push(render_pixels(&settings, &demo, &text, size));
69 - labels.push("1. Start (jasny, PL)".into());
69 + labels.push("1. Start (light, PL)".into());
70 70
71 71 // Pomocniczo: aktualny layout i wysłanie kliknięcia.
72 72 macro_rules! layout {
@@ -94,10 +94,10 @@ fn main() -> Result<(), Box<dyn Error>> {
94 94 assert_eq!(
95 95 settings.preference(),
96 96 ThemePreference::Dark,
97 - "motyw nie przeszedł na ciemny"
97 + "theme did not switch to Dark"
98 98 );
99 99 frames.push(render_pixels(&settings, &demo, &text, size));
100 - labels.push("2. Motyw: Ciemny".into());
100 + labels.push("2. Theme: Dark".into());
101 101
102 102 // 3. Klik kropki akcentu (Purple = indeks 7).
103 103 let c = layout!().accents[7].center();
@@ -105,45 +105,49 @@ fn main() -> Result<(), Box<dyn Error>> {
105 105 assert_eq!(
106 106 settings.accent(),
107 107 Accent::Purple,
108 - "akcent nie ustawił się na Purple"
108 + "accent did not switch to Purple"
109 109 );
110 110 frames.push(render_pixels(&settings, &demo, &text, size));
111 - labels.push("3. Akcent: Purple".into());
111 + labels.push("3. Accent: Purple".into());
112 112
113 113 // 4. Klik pozycji „Sieć" w menu nawigacji (indeks elementu 5).
114 114 let theme = settings.resolve(false);
115 115 let c = make_nav().rows(layout!().sidebar, &theme)[5].rect.center();
116 116 click!(c);
117 - assert_eq!(demo.nav_selected, Some(5), "nie zaznaczono pozycji Sieć");
117 + assert_eq!(
118 + demo.nav_selected,
119 + Some(5),
120 + "nav item 'Network' not selected"
121 + );
118 122 frames.push(render_pixels(&settings, &demo, &text, size));
119 - labels.push("4. Nawigacja: Sieć".into());
123 + labels.push("4. Navigation: Network".into());
120 124
121 125 // 5. Klik „Siatka" w przełączniku widoku.
122 126 let c = ViewSwitcher::new(["a", "b"]).segments(layout!().view_switcher)[1].center();
123 127 click!(c);
124 - assert_eq!(demo.view_mode, 1, "widok nie przeszedł na Siatkę");
128 + assert_eq!(demo.view_mode, 1, "view did not switch to Grid");
125 129 frames.push(render_pixels(&settings, &demo, &text, size));
126 - labels.push("5. Widok: Siatka".into());
130 + labels.push("5. View: Grid".into());
127 131
128 132 // 6. Przełączenie zakładki (TabView + TabBar).
129 133 let theme = settings.resolve(false);
130 134 let c = ui::tab_bar(&demo).segments(layout!().tabs, &text, &theme)[2].center();
131 135 click!(c);
132 - assert_eq!(demo.tabs.selected(), 2, "zakładka się nie przełączyła");
136 + assert_eq!(demo.tabs.selected(), 2, "tab did not switch");
133 137 frames.push(render_pixels(&settings, &demo, &text, size));
134 - labels.push("6. Zakładka: O aplikacji".into());
138 + labels.push("6. Tab: About".into());
135 139
136 140 // 7. Klik ikony ◧ w HeaderBarze — zwinięcie paska bocznego.
137 141 let c = layout!().sidebar_button.center();
138 142 click!(c);
139 - assert!(!demo.sidebar_visible, "pasek boczny się nie zwinął");
143 + assert!(!demo.sidebar_visible, "sidebar did not collapse");
140 144 frames.push(render_pixels(&settings, &demo, &text, size));
141 - labels.push("7. Pasek boczny zwinięty ◧".into());
145 + labels.push("7. Sidebar collapsed \u{25e7}".into());
142 146
143 147 // 8. Klik ikony „☰” — otwarcie popoveru (menu nawigacji).
144 148 let c = layout!().burger.center();
145 149 click!(c);
146 - assert_eq!(demo.popover, Some(Popover::Menu), "menu się nie otworzyło");
150 + assert_eq!(demo.popover, Some(Popover::Menu), "menu did not open");
147 151 // Podświetlenie drugiej pozycji, żeby pokazać hover.
148 152 let theme = settings.resolve(false);
149 153 if let Some((panel, menu)) = ui::popover_menu(size, &theme, &text, &layout!(), &demo) {
@@ -161,43 +165,43 @@ fn main() -> Result<(), Box<dyn Error>> {
161 165 );
162 166 }
163 167 frames.push(render_pixels(&settings, &demo, &text, size));
164 - labels.push("8. Menu ☰ otwarte".into());
168 + labels.push("8. Menu \u{2630} open".into());
165 169
166 170 // 9. Klik „O aplikacji” w otwartym menu → dolny panel (BottomSheet + Pager).
167 171 let theme = settings.resolve(false);
168 172 let about = ui::popover_menu(size, &theme, &text, &layout!(), &demo)
169 173 .map(|(panel, menu)| menu.rows(panel, &theme)[4].rect.center())
170 - .expect("menu otwarte");
174 + .expect("menu is open");
171 175 click!(about);
172 - assert!(demo.sheet.is_open(), "panel się nie otworzył");
176 + assert!(demo.sheet.is_open(), "bottom sheet did not open");
173 177 frames.push(render_pixels(&settings, &demo, &text, size));
174 - labels.push("9. Dolny panel \u{201e}O aplikacji\u{201d}".into());
178 + labels.push("9. Bottom sheet \u{201c}About\u{201d}".into());
175 179
176 180 // 10. Zamknięcie panelu (klik w tło) i rozwinięcie listy języków (DropDown + Menu).
177 181 click!(Point::new(120.0, 300.0));
178 - assert!(!demo.sheet.is_open(), "panel się nie zamknął");
182 + assert!(!demo.sheet.is_open(), "bottom sheet did not close");
179 183 let c = layout!().language.center();
180 184 click!(c);
181 185 assert_eq!(
182 186 demo.popover,
183 187 Some(Popover::Language),
184 - "lista języków się nie rozwinęła"
188 + "language list did not open"
185 189 );
186 190 frames.push(render_pixels(&settings, &demo, &text, size));
187 - labels.push("10. Wybór języka (DropDown)".into());
191 + labels.push("10. Language selection (DropDown)".into());
188 192
189 193 // 11. Popover „Opcje” (rozmiar ikon / sortowanie / ukryte pliki).
190 194 click!(Point::new(450.0, 300.0)); // zamknij popover języka
191 - assert!(demo.popover.is_none(), "popover się nie zamknął");
195 + assert!(demo.popover.is_none(), "popover did not close");
192 196 let c = layout!().options_button.center();
193 197 click!(c);
194 198 assert_eq!(
195 199 demo.popover,
196 200 Some(Popover::Options),
197 - "popover opcji się nie otworzył"
201 + "options popover did not open"
198 202 );
199 203 frames.push(render_pixels(&settings, &demo, &text, size));
200 - labels.push("11. Popover \u{201e}Opcje\u{201d}".into());
204 + labels.push("11. Options popover".into());
201 205
202 206 // 12. Klik popovera (zamknięcie) i zmiana akcentu → powiadomienie (Toast) z „Cofnij”.
203 207 click!(Point::new(450.0, 300.0));
@@ -206,33 +210,33 @@ fn main() -> Result<(), Box<dyn Error>> {
206 210 assert_eq!(
207 211 settings.accent(),
208 212 Accent::Teal,
209 - "akcent nie ustawił się na Teal"
213 + "accent did not switch to Teal"
210 214 );
211 - assert!(demo.toast.is_open(), "powiadomienie się nie pokazało");
215 + assert!(demo.toast.is_open(), "toast did not appear");
212 216 frames.push(render_pixels(&settings, &demo, &text, size));
213 - labels.push("12. Powiadomienie (Toast)".into());
217 + labels.push("12. Toast".into());
214 218
215 219 // 13. Klik „Cofnij” w powiadomieniu → powrót akcentu, powiadomienie znika.
216 220 let theme = settings.resolve(false);
217 221 let undo = demo
218 222 .toast
219 223 .action_rect(size, &theme, &text)
220 - .expect("akcja powiadomienia")
224 + .expect("toast action")
221 225 .center();
222 226 click!(undo);
223 227 assert_eq!(
224 228 settings.accent(),
225 229 Accent::Purple,
226 - "akcent nie wrócił po „Cofnij”"
230 + "accent did not revert after Undo"
227 231 );
228 - assert!(!demo.toast.is_open(), "powiadomienie nie zniknęło");
232 + assert!(!demo.toast.is_open(), "toast did not disappear");
229 233 frames.push(render_pixels(&settings, &demo, &text, size));
230 - labels.push("13. Cofnięto akcent".into());
234 + labels.push("13. Accent reverted".into());
231 235
232 236 // 14. Filtr bez wyników → ekran stanu (StatusPage) z akcją „Wyczyść”.
233 237 let c = layout!().search.center();
234 238 click!(c);
235 - assert!(demo.search.is_focused(), "pole wyszukiwania bez fokusu");
239 + assert!(demo.search.is_focused(), "search field is not focused");
236 240 for ch in ['x', 'y', 'z'] {
237 241 let key = Event::Key(KeyEvent {
238 242 keysym: ch as u32,
@@ -246,30 +250,33 @@ fn main() -> Result<(), Box<dyn Error>> {
246 250 }
247 251 assert!(
248 252 ui::empty_state(&demo).is_some(),
249 - "brak ekranu stanu dla braku wyników"
253 + "status page missing for empty search"
250 254 );
251 255 frames.push(render_pixels(&settings, &demo, &text, size));
252 - labels.push("14. Brak wyników (StatusPage)".into());
256 + labels.push("14. No results (StatusPage)".into());
253 257
254 258 // 15. Klik „Wyczyść” w ekranie stanu → lista wraca.
255 259 let theme = settings.resolve(false);
256 260 let clear = ui::empty_state(&demo)
257 - .expect("ekran stanu")
261 + .expect("status page")
258 262 .rects(layout!().items, &theme)
259 263 .action
260 - .expect("akcja ekranu stanu")
264 + .expect("status page action")
261 265 .center();
262 266 click!(clear);
263 - assert!(demo.search.is_empty(), "filtr nie został wyczyszczony");
264 - assert!(ui::empty_state(&demo).is_none(), "ekran stanu nie zniknął");
267 + assert!(demo.search.is_empty(), "search filter was not cleared");
268 + assert!(
269 + ui::empty_state(&demo).is_none(),
270 + "status page did not disappear"
271 + );
265 272 frames.push(render_pixels(&settings, &demo, &text, size));
266 - labels.push("15. Filtr wyczyszczony".into());
273 + labels.push("15. Filter cleared".into());
267 274
268 275 // Zapis klatek.
269 276 for (i, pixels) in frames.iter().enumerate() {
270 277 let path = format!("docs/images/demo-step-{}.png", i + 1);
271 278 save_png(&path, pixels)?;
272 - println!("zapisano {path} — {}", labels[i]);
279 + println!("saved {path} — {}", labels[i]);
273 280 }
274 281
275 282 // Montaż (siatka `cols` x `rows`) na zmienną liczbę klatek.
@@ -290,11 +297,8 @@ fn main() -> Result<(), Box<dyn Error>> {
290 297 montage.draw_pixmap(cx as i32, cy as i32, src.as_ref(), &paint, scale, None);
291 298 }
292 299 montage.save_png("docs/images/demo-montage.png")?;
293 - println!("zapisano docs/images/demo-montage.png");
300 + println!("saved docs/images/demo-montage.png");
294 301
295 - println!(
296 - "\nWszystkie interakcje przeszły pomyślnie ({} klatek).",
297 - frames.len()
298 - );
302 + println!("\nAll interactions passed ({} frames).", frames.len());
299 303 Ok(())
300 304 }
@@ -148,7 +148,7 @@ fn clicking_path_component_navigates_up() {
148 148 .iter()
149 149 .find(|(pick, _)| *pick == Some(0))
150 150 .map(|(_, r)| r.center())
151 - .expect("pierwszy składnik ścieżki widoczny");
151 + .expect("first path component is visible");
152 152 click(&mut settings, &mut demo, first);
153 153 assert_eq!(demo.path.len(), 1);
154 154 }
@@ -281,7 +281,7 @@ fn window_controls_are_widget_managed() {
281 281 let mut demo = Demo::default();
282 282 let header = layout(&settings, &demo).header;
283 283
284 - let close = header.close.expect("kontrolki po prawej").center();
284 + let close = header.close.expect("window controls on the right").center();
285 285 click(&mut settings, &mut demo, close);
286 286 assert!(demo.pending_close);
287 287
@@ -327,7 +327,7 @@ fn accent_change_shows_toast_and_undo_reverts() {
327 327 let undo = demo
328 328 .toast
329 329 .action_rect(size(), &theme, &text)
330 - .expect("akcja powiadomienia")
330 + .expect("toast action")
331 331 .center();
332 332 click(&mut settings, &mut demo, undo);
333 333 assert_eq!(settings.accent(), Accent::default());
@@ -342,10 +342,10 @@ fn search_without_results_shows_empty_state_that_clears() {
342 342
343 343 let theme = settings.resolve(false);
344 344 let action = ui::empty_state(&demo)
345 - .expect("ekran stanu dla braku wyników")
345 + .expect("status page for empty search")
346 346 .rects(layout(&settings, &demo).items, &theme)
347 347 .action
348 - .expect("przycisk akcji")
348 + .expect("action button")
349 349 .center();
350 350 click(&mut settings, &mut demo, action);
351 351 assert!(demo.search.is_empty());
@@ -362,7 +362,7 @@ fn search_filters_items_and_selection_maps_to_full_list() {
362 362 assert_eq!(
363 363 visible.len(),
364 364 1,
365 - "filtr powinien zawęzić listę do jednego elementu"
365 + "filter should narrow the list to one item"
366 366 );
367 367 let view = ui::item_view(&demo);
368 368 assert_eq!(view.len(), 1);
@@ -192,10 +192,10 @@ where
192 192 WaylandSource::new(conn.clone(), event_queue).insert(loop_handle)?;
193 193
194 194 let compositor = CompositorState::bind(&globals, &qh)
195 - .map_err(|e| format!("wl_compositor niedostępny: {e}"))?;
195 + .map_err(|e| format!("wl_compositor unavailable: {e}"))?;
196 196 let xdg_shell =
197 - XdgShell::bind(&globals, &qh).map_err(|e| format!("xdg-shell niedostępny: {e}"))?;
198 - let shm = Shm::bind(&globals, &qh).map_err(|e| format!("wl_shm niedostępny: {e}"))?;
197 + XdgShell::bind(&globals, &qh).map_err(|e| format!("xdg-shell unavailable: {e}"))?;
198 + let shm = Shm::bind(&globals, &qh).map_err(|e| format!("wl_shm unavailable: {e}"))?;
199 199
200 200 let surface = compositor.create_surface(&qh);
201 201 // CSD: sami rysujemy HeaderBar (brak dekoracji serwera).
@@ -371,7 +371,7 @@ impl App {
371 371 stride,
372 372 wl_shm::Format::Argb8888,
373 373 )
374 - .expect("alokacja bufora shm")
374 + .expect("shm buffer allocation")
375 375 .0
376 376 });
377 377
@@ -387,7 +387,7 @@ impl App {
387 387 stride,
388 388 wl_shm::Format::Argb8888,
389 389 )
390 - .expect("alokacja drugiego bufora shm");
390 + .expect("second shm buffer allocation");
391 391 *buffer = second;
392 392 canvas
393 393 }
@@ -409,7 +409,7 @@ impl App {
409 409
410 410 let surface = self.window.wl_surface();
411 411 surface.damage_buffer(0, 0, phys_w as i32, phys_h as i32);
412 - buffer.attach_to(surface).expect("podłączenie bufora");
412 + buffer.attach_to(surface).expect("buffer attach");
413 413 self.window.commit();
414 414 }
415 415 }
@@ -23,7 +23,7 @@ impl SoftwareRenderer {
23 23 /// Tworzy renderer o zadanym rozmiarze **fizycznym** (piksele).
24 24 pub fn new(width: u32, height: u32) -> Self {
25 25 Self {
26 - pixmap: Pixmap::new(width.max(1), height.max(1)).expect("alokacja bufora"),
26 + pixmap: Pixmap::new(width.max(1), height.max(1)).expect("buffer allocation"),
27 27 text: TextEngine::system(),
28 28 }
29 29 }
@@ -31,7 +31,7 @@ impl SoftwareRenderer {
31 31 /// Zmienia rozmiar bufora (zawartość jest zerowana).
32 32 pub fn resize(&mut self, width: u32, height: u32) {
33 33 if self.pixmap.width() != width.max(1) || self.pixmap.height() != height.max(1) {
34 - self.pixmap = Pixmap::new(width.max(1), height.max(1)).expect("realokacja bufora");
34 + self.pixmap = Pixmap::new(width.max(1), height.max(1)).expect("buffer reallocation");
35 35 }
36 36 }
37 37
@@ -272,12 +272,12 @@ mod tests {
272 272
273 273 // Środek prostokąta jest czerwony.
274 274 let c = pixel(&r, 30, 30);
275 - assert!(c[0] > 200 && c[1] < 40 && c[2] < 40, "środek: {c:?}");
275 + assert!(c[0] > 200 && c[1] < 40 && c[2] < 40, "center: {c:?}");
276 276 // Narożnik kwadratu (10,10) wypada poza zaokrąglenie → tło.
277 277 let corner = pixel(&r, 10, 10);
278 278 assert!(
279 279 corner[0] > 200 && corner[1] > 200 && corner[2] > 200,
280 - "róg: {corner:?}"
280 + "corner: {corner:?}"
281 281 );
282 282 }
283 283
@@ -48,12 +48,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
48 48 .with_color(fg),
49 49 );
50 50 scene.text(
51 - TextRun::new(
52 - Point::new(24.0, 168.0),
53 - "Kliknij gdziekolwiek, aby przełączyć",
54 - 14.0,
55 - )
56 - .with_color(theme.colors.dim_text),
51 + TextRun::new(Point::new(24.0, 168.0), "Click anywhere to toggle", 14.0)
52 + .with_color(theme.colors.dim_text),
57 53 );
58 54 })
59 55 }
@@ -10,7 +10,7 @@
10 10 set -eu
11 11
12 12 if [ "$#" -lt 1 ]; then
13 - echo "użycie: libluna-new.sh <katalog-aplikacji> [nazwa-pakietu]" >&2
13 + echo "usage: libluna-new.sh <app-dir> [package-name]" >&2
14 14 exit 1
15 15 fi
16 16
@@ -23,7 +23,7 @@ libluna_path="$root/crates/libluna"
23 23 template="$root/templates/minimal-app"
24 24
25 25 if [ ! -d "$template" ]; then
26 - echo "nie znaleziono szablonu: $template" >&2
26 + echo "template not found: $template" >&2
27 27 exit 1
28 28 fi
29 29
@@ -34,7 +34,7 @@ sed "s#__APP_NAME__#$name#g; s#__LIBLUNA_PATH__#$libluna_path#g" \
34 34 sed "s#__APP_NAME__#$name#g" \
35 35 "$template/src/main.rs" > "$target/src/main.rs"
36 36
37 -echo "utworzono aplikację: $target"
38 -echo " pakiet: $name"
37 +echo "created application: $target"
38 +echo " package: $name"
39 39 echo " libluna: $libluna_path"
40 -echo "uruchom: (cd $target && cargo run)"
40 +echo "run: (cd $target && cargo run)"