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)"