KiCad PCB EDA Suite
Loading...
Searching...
No Matches
template_default_html.h
Go to the documentation of this file.
1/*
2 * KiCad Project Template HTML defaults
3 * Extracted from dialog_template_selector.cpp to allow reuse and to provide
4 * a styled fallback page when a template does not supply an info.html.
5 */
6
7#ifndef KICAD_TEMPLATE_DEFAULT_HTML_H
8#define KICAD_TEMPLATE_DEFAULT_HTML_H
9
10#include <wx/string.h>
11
12// Uses _() translation macro which is defined globally in KiCad builds.
13
14namespace
15{
16
17// Common CSS variables and base styles shared across all template HTML pages.
18inline wxString GetCommonStyles()
19{
20 return wxString( R"(
21:root {
22 color-scheme: light dark;
23
24 --bg-primary: light-dark(#FFFFFF, #1E1E1E);
25 --bg-secondary: light-dark(#F3F3F3, #2D2D2D);
26 --bg-elevated: light-dark(#FFFFFF, #333333);
27 --text-primary: light-dark(#1F2328, #DED3DD);
28 --text-secondary: light-dark(#545454, #848484);
29 --accent: light-dark(#1A81C4, #42B8EB);
30 --accent-subtle: light-dark(rgba(26, 129, 196, 0.08), rgba(66, 184, 235, 0.1));
31 --border: light-dark(#E0E0E0, #404040);
32 --shadow: light-dark(0 1px 3px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.2));
33}
34
35body {
36 background-color: var(--bg-primary);
37 color: var(--text-primary);
38 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
39}
40
41a, a:link {
42 color: light-dark(#0D4A8B, #A7D7FC);
43}
44
45a:hover{
46 color: light-dark(#0A2540, #EBF5FE);
47}
48
49a:visited {
50 color: light-dark(#7C3EAE, #E9DDFC);
51}
52
53img {
54 max-width: 100%;
55 height: auto;
56}
57
58)" );
59}
60
61// SVG icon for template/document
62inline wxString GetTemplateIcon()
63{
64 return wxString(
65 "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" "
66 "stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">"
67 "<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/>"
68 "<polyline points=\"14 2 14 8 20 8\"/>"
69 "<line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/>"
70 "<line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>"
71 "<polyline points=\"10 9 9 9 8 9\"/>"
72 "</svg>"
73 );
74}
75
76// SVG icon for settings/gear
77inline wxString GetSettingsIcon()
78{
79 return wxString(
80 "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" "
81 "stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">"
82 "<circle cx=\"12\" cy=\"12\" r=\"3\"/>"
83 "<path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06"
84 "a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09"
85 "A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83"
86 "l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09"
87 "A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0"
88 "l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09"
89 "a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83"
90 "l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09"
91 "a1.65 1.65 0 0 0-1.51 1z\"/>"
92 "</svg>"
93 );
94}
95
96// SVG icon for layers/stack
97inline wxString GetLayersIcon()
98{
99 return wxString(
100 "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" "
101 "stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">"
102 "<polygon points=\"12 2 2 7 12 12 22 7 12 2\"/>"
103 "<polyline points=\"2 17 12 22 22 17\"/>"
104 "<polyline points=\"2 12 12 17 22 12\"/>"
105 "</svg>"
106 );
107}
108
109// SVG icon for folder
110inline wxString GetFolderIcon()
111{
112 return wxString(
113 "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" "
114 "stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">"
115 "<path d=\"M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z\"/>"
116 "</svg>"
117 );
118}
119
120// SVG icon for info/lightbulb
121inline wxString GetInfoIcon()
122{
123 return wxString(
124 "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" "
125 "stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">"
126 "<circle cx=\"12\" cy=\"12\" r=\"10\"/>"
127 "<line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"/>"
128 "<line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"/>"
129 "</svg>"
130 );
131}
132
133} // anonymous namespace
134
135
136// Welcome page shown when no template is selected.
137inline wxString GetWelcomeHtml( bool aDarkMode )
138{
139 wxString bodyClass = aDarkMode ? wxS( "kicad-dark" ) : wxS( "" );
140
141 return wxString(
142 "<!DOCTYPE html>"
143 "<html lang=\"en\">"
144 "<head>"
145 "<meta charset=\"UTF-8\">"
146 "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
147 "<title>KiCad Project Template Selector</title>"
148 "<style>" )
149 + GetCommonStyles() +
150 wxString(
151 ".card {"
152 "max-width: 600px;"
153 "margin: 0 auto;"
154 "background: var(--bg-elevated);"
155 "border-radius: 8px;"
156 "padding: 32px;"
157 "box-shadow: var(--shadow);"
158 "border: 1px solid var(--border);"
159 "}"
160 ".header {"
161 "text-align: center;"
162 "margin-bottom: 28px;"
163 "}"
164 ".title {"
165 "font-size: 1.5rem;"
166 "font-weight: 600;"
167 "color: var(--text-primary);"
168 "margin: 0 0 8px 0;"
169 "}"
170 ".subtitle {"
171 "font-size: 0.95rem;"
172 "color: var(--text-secondary);"
173 "margin: 0;"
174 "}"
175 ".features {"
176 "display: flex;"
177 "flex-direction: column;"
178 "gap: 16px;"
179 "margin-bottom: 28px;"
180 "}"
181 ".feature {"
182 "display: flex;"
183 "align-items: flex-start;"
184 "gap: 14px;"
185 "padding: 14px;"
186 "background: var(--bg-secondary);"
187 "border-radius: 6px;"
188 "}"
189 ".feature-icon {"
190 "flex-shrink: 0;"
191 "width: 40px;"
192 "height: 40px;"
193 "display: flex;"
194 "align-items: center;"
195 "justify-content: center;"
196 "background: var(--accent-subtle);"
197 "border-radius: 8px;"
198 "color: var(--accent);"
199 "}"
200 ".feature-content h3 {"
201 "margin: 0 0 4px 0;"
202 "font-size: 0.95rem;"
203 "font-weight: 600;"
204 "color: var(--text-primary);"
205 "}"
206 ".feature-content p {"
207 "margin: 0;"
208 "font-size: 0.875rem;"
209 "color: var(--text-secondary);"
210 "}"
211 ".tip {"
212 "display: flex;"
213 "align-items: flex-start;"
214 "gap: 10px;"
215 "padding: 12px 14px;"
216 "background: var(--accent-subtle);"
217 "border-radius: 6px;"
218 "border-left: 3px solid var(--accent);"
219 "}"
220 ".tip-icon {"
221 "flex-shrink: 0;"
222 "color: var(--accent);"
223 "}"
224 ".tip-text {"
225 "font-size: 0.875rem;"
226 "color: var(--text-secondary);"
227 "margin: 0;"
228 "}"
229 "</style>"
230 "</head>"
231 "<body class=\"" ) + bodyClass + wxString( "\">"
232 "<div class=\"card\">"
233 "<div class=\"header\">"
234 "<h1 class=\"title\">" ) + _( "Select a Template" ) + wxString( "</h1>"
235 "<p class=\"subtitle\">" )
236 + _( "Templates provide pre-configured project structures to jumpstart your design." )
237 + wxString( "</p>"
238 "</div>"
239 "<div class=\"features\">"
240 "<div class=\"feature\">"
241 "<div class=\"feature-icon\">" ) + GetTemplateIcon() + wxString( "</div>"
242 "<div class=\"feature-content\">"
243 "<h3>" ) + _( "Pre-configured Libraries" ) + wxString( "</h3>"
244 "<p>" ) + _( "Common symbols and footprints already linked and ready to use." ) + wxString( "</p>"
245 "</div>"
246 "</div>"
247 "<div class=\"feature\">"
248 "<div class=\"feature-icon\">" ) + GetSettingsIcon() + wxString( "</div>"
249 "<div class=\"feature-content\">"
250 "<h3>" ) + _( "Design Rules" ) + wxString( "</h3>"
251 "<p>" ) + _( "Electrical and mechanical constraints configured for the intended application." ) + wxString( "</p>"
252 "</div>"
253 "</div>"
254 "<div class=\"feature\">"
255 "<div class=\"feature-icon\">" ) + GetLayersIcon() + wxString( "</div>"
256 "<div class=\"feature-content\">"
257 "<h3>" ) + _( "Board Stackups" ) + wxString( "</h3>"
258 "<p>" ) + _( "Layer configurations optimized for common manufacturing processes." ) + wxString( "</p>"
259 "</div>"
260 "</div>"
261 "</div>"
262 "<div class=\"tip\">"
263 "<div class=\"tip-icon\">" ) + GetInfoIcon() + wxString( "</div>"
264 "<p class=\"tip-text\">" )
265 + _( "Recently used templates appear at the top. Use the folder icon to browse custom template directories." )
266 + wxString( "</p>"
267 "</div>"
268 "</div>"
269 "</body>"
270 "</html>"
271 );
272}
273
274
275// Fallback when a specific template has no meta/info.html.
276inline wxString GetTemplateInfoHtml( const wxString& aTemplateName, bool aDarkMode )
277{
278 wxString bodyClass = aDarkMode ? wxS( "kicad-dark" ) : wxS( "" );
279
280 return wxString(
281 "<!DOCTYPE html>"
282 "<html lang=\"en\">"
283 "<head>"
284 "<meta charset=\"UTF-8\">"
285 "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
286 "<title>" ) + aTemplateName + wxString( " - KiCad Template</title>"
287 "<style>" )
288 + GetCommonStyles() +
289 wxString(
290 ".card {"
291 "max-width: 600px;"
292 "margin: 0 auto;"
293 "background: var(--bg-elevated);"
294 "border-radius: 8px;"
295 "padding: 28px;"
296 "box-shadow: var(--shadow);"
297 "border: 1px solid var(--border);"
298 "}"
299 ".header {"
300 "display: flex;"
301 "align-items: center;"
302 "gap: 12px;"
303 "margin-bottom: 20px;"
304 "}"
305 ".badge {"
306 "background: var(--accent);"
307 "color: #FFFFFF;"
308 "padding: 4px 10px;"
309 "border-radius: 4px;"
310 "font-size: 0.75rem;"
311 "font-weight: 600;"
312 "letter-spacing: 0.03em;"
313 "text-transform: uppercase;"
314 "}"
315 ".template-name {"
316 "font-size: 1.25rem;"
317 "font-weight: 600;"
318 "color: var(--text-primary);"
319 "margin: 0;"
320 "}"
321 ".description {"
322 "color: var(--text-secondary);"
323 "margin-bottom: 24px;"
324 "}"
325 ".steps {"
326 "background: var(--bg-secondary);"
327 "border-radius: 6px;"
328 "padding: 20px;"
329 "margin-bottom: 20px;"
330 "}"
331 ".steps-title {"
332 "font-size: 0.875rem;"
333 "font-weight: 600;"
334 "color: var(--text-primary);"
335 "margin: 0 0 16px 0;"
336 "}"
337 ".step {"
338 "display: flex;"
339 "gap: 12px;"
340 "margin-bottom: 14px;"
341 "}"
342 ".step:last-child {"
343 "margin-bottom: 0;"
344 "}"
345 ".step-number {"
346 "flex-shrink: 0;"
347 "width: 24px;"
348 "height: 24px;"
349 "display: flex;"
350 "align-items: center;"
351 "justify-content: center;"
352 "background: var(--accent);"
353 "color: #FFFFFF;"
354 "border-radius: 50%;"
355 "font-size: 0.75rem;"
356 "font-weight: 600;"
357 "}"
358 ".step-content h4 {"
359 "margin: 0 0 2px 0;"
360 "font-size: 0.875rem;"
361 "font-weight: 600;"
362 "color: var(--text-primary);"
363 "}"
364 ".step-content p {"
365 "margin: 0;"
366 "font-size: 0.8125rem;"
367 "color: var(--text-secondary);"
368 "}"
369 ".hint {"
370 "display: flex;"
371 "align-items: flex-start;"
372 "gap: 10px;"
373 "padding: 12px 14px;"
374 "background: var(--accent-subtle);"
375 "border-radius: 6px;"
376 "border-left: 3px solid var(--accent);"
377 "}"
378 ".hint-icon {"
379 "flex-shrink: 0;"
380 "color: var(--accent);"
381 "}"
382 ".hint-text {"
383 "font-size: 0.8125rem;"
384 "color: var(--text-secondary);"
385 "margin: 0;"
386 "}"
387 "code {"
388 "background: var(--bg-secondary);"
389 "padding: 2px 6px;"
390 "border-radius: 3px;"
391 "font-size: 0.8125rem;"
392 "font-family: 'SF Mono', Monaco, Consolas, monospace;"
393 "}"
394 "</style>"
395 "</head>"
396 "<body class=\"" ) + bodyClass + wxString( "\">"
397 "<div class=\"card\">"
398 "<div class=\"header\">"
399 "<span class=\"badge\">" ) + _( "Template" ) + wxString( "</span>"
400 "<h1 class=\"template-name\">" ) + aTemplateName + wxString( "</h1>"
401 "</div>"
402 "<p class=\"description\">" )
403 + _( "This template does not include a description. You can still use it to create a new project." )
404 + wxString( "</p>"
405 "<div class=\"steps\">"
406 "<h3 class=\"steps-title\">" ) + _( "To use this template" ) + wxString( "</h3>"
407 "<div class=\"step\">"
408 "<span class=\"step-number\">1</span>"
409 "<div class=\"step-content\">"
410 "<h4>" ) + _( "Create the project" ) + wxString( "</h4>"
411 "<p>" ) + _( "Click OK to create a new project folder with this template's contents." ) + wxString( "</p>"
412 "</div>"
413 "</div>"
414 "<div class=\"step\">"
415 "<span class=\"step-number\">2</span>"
416 "<div class=\"step-content\">"
417 "<h4>" ) + _( "Open schematic and PCB" ) + wxString( "</h4>"
418 "<p>" ) + _( "Use the Project Manager to launch the Schematic and PCB editors." ) + wxString( "</p>"
419 "</div>"
420 "</div>"
421 "<div class=\"step\">"
422 "<span class=\"step-number\">3</span>"
423 "<div class=\"step-content\">"
424 "<h4>" ) + _( "Review settings" ) + wxString( "</h4>"
425 "<p>" ) + _( "Verify libraries, design rules, and board stackup match your needs." ) + wxString( "</p>"
426 "</div>"
427 "</div>"
428 "</div>"
429 "<div class=\"hint\">"
430 "<div class=\"hint-icon\">" ) + GetInfoIcon() + wxString( "</div>"
431 "<p class=\"hint-text\">" )
432 + _( "Add a description by creating" ) + wxString( " <code>meta/info.html</code> " )
433 + _( "inside this template's directory." )
434 + wxString( "</p>"
435 "</div>"
436 "</div>"
437 "</body>"
438 "</html>"
439 );
440}
441
442
443// Page shown when a template directory has no templates.
444inline wxString GetNoTemplatesHtml( bool aDarkMode )
445{
446 wxString bodyClass = aDarkMode ? wxS( "kicad-dark" ) : wxS( "" );
447
448 return wxString(
449 "<!DOCTYPE html>"
450 "<html lang=\"en\">"
451 "<head>"
452 "<meta charset=\"UTF-8\">"
453 "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
454 "<title>No Templates - KiCad</title>"
455 "<style>" )
456 + GetCommonStyles() +
457 wxString(
458 ".card {"
459 "max-width: 500px;"
460 "margin: 0 auto;"
461 "background: var(--bg-elevated);"
462 "border-radius: 8px;"
463 "padding: 32px;"
464 "box-shadow: var(--shadow);"
465 "border: 1px solid var(--border);"
466 "text-align: center;"
467 "}"
468 ".icon {"
469 "width: 56px;"
470 "height: 56px;"
471 "margin: 0 auto 20px auto;"
472 "display: flex;"
473 "align-items: center;"
474 "justify-content: center;"
475 "background: var(--bg-secondary);"
476 "border-radius: 50%;"
477 "color: var(--text-secondary);"
478 "}"
479 ".icon svg {"
480 "width: 28px;"
481 "height: 28px;"
482 "}"
483 ".title {"
484 "font-size: 1.25rem;"
485 "font-weight: 600;"
486 "color: var(--text-primary);"
487 "margin: 0 0 8px 0;"
488 "}"
489 ".message {"
490 "color: var(--text-secondary);"
491 "margin: 0 0 24px 0;"
492 "}"
493 ".suggestions {"
494 "text-align: left;"
495 "background: var(--bg-secondary);"
496 "border-radius: 6px;"
497 "padding: 16px 20px;"
498 "margin-bottom: 20px;"
499 "}"
500 ".suggestions-title {"
501 "font-size: 0.875rem;"
502 "font-weight: 600;"
503 "color: var(--text-primary);"
504 "margin: 0 0 12px 0;"
505 "}"
506 ".suggestions ul {"
507 "margin: 0;"
508 "padding-left: 20px;"
509 "color: var(--text-secondary);"
510 "font-size: 0.875rem;"
511 "}"
512 ".suggestions li {"
513 "margin-bottom: 8px;"
514 "}"
515 ".suggestions li:last-child {"
516 "margin-bottom: 0;"
517 "}"
518 ".tip {"
519 "display: flex;"
520 "align-items: flex-start;"
521 "gap: 10px;"
522 "padding: 12px 14px;"
523 "background: var(--accent-subtle);"
524 "border-radius: 6px;"
525 "text-align: left;"
526 "}"
527 ".tip-icon {"
528 "flex-shrink: 0;"
529 "color: var(--accent);"
530 "}"
531 ".tip-text {"
532 "font-size: 0.8125rem;"
533 "color: var(--text-secondary);"
534 "margin: 0;"
535 "}"
536 "</style>"
537 "</head>"
538 "<body class=\"" ) + bodyClass + wxString( "\">"
539 "<div class=\"card\">"
540 "<div class=\"icon\">" ) + GetFolderIcon() + wxString( "</div>"
541 "<h1 class=\"title\">" ) + _( "No Templates Found" ) + wxString( "</h1>"
542 "<p class=\"message\">" )
543 + _( "The selected directory does not contain any project templates." )
544 + wxString( "</p>"
545 "<div class=\"suggestions\">"
546 "<h3 class=\"suggestions-title\">" ) + _( "Suggestions" ) + wxString( "</h3>"
547 "<ul>"
548 "<li>" ) + _( "Browse to a different directory using the folder icon" ) + wxString( "</li>"
549 "<li>" ) + _( "Use the refresh icon to reload the current directory" ) + wxString( "</li>"
550 "<li>" ) + _( "Switch to a system templates tab" ) + wxString( "</li>"
551 "</ul>"
552 "</div>"
553 "<div class=\"tip\">"
554 "<div class=\"tip-icon\">" ) + GetInfoIcon() + wxString( "</div>"
555 "<p class=\"tip-text\">" )
556 + _( "Each template needs a 'meta' folder containing configuration files." )
557 + wxString( "</p>"
558 "</div>"
559 "</div>"
560 "</body>"
561 "</html>"
562 );
563}
564
565#endif // KICAD_TEMPLATE_DEFAULT_HTML_H
#define _(s)
wxString GetWelcomeHtml(bool aDarkMode)
wxString GetTemplateInfoHtml(const wxString &aTemplateName, bool aDarkMode)
wxString GetNoTemplatesHtml(bool aDarkMode)