feat: add modular Lardon3D TUI layout

This commit is contained in:
fy59 2026-08-06 14:20:36 +02:00
parent 47cf116785
commit 474831329d
11 changed files with 156 additions and 100 deletions

View file

@ -1,6 +1,6 @@
# Scan3D Vulkan # Lardon3D
Scan3D Vulkan est une application terminal interactive dédiée à la reconstruction 3D. Cette première interface TUI utilise tout l'espace du terminal et s'adapte à son redimensionnement. Lardon3D est une application terminal interactive dédiée à la reconstruction 3D. Son interface TUI utilise tout l'espace du terminal et s'adapte à son redimensionnement.
Une vue Vulkan séparée sera ajoutée ultérieurement pour afficher la scène 3D. L'application actuelle n'ouvre aucune fenêtre graphique. Une vue Vulkan séparée sera ajoutée ultérieurement pour afficher la scène 3D. L'application actuelle n'ouvre aucune fenêtre graphique.
@ -22,7 +22,7 @@ meson compile -C build -j8
## Exécution ## Exécution
```sh ```sh
./build/scan3d-vulkan ./build/lardon3d
``` ```
La TUI s'affiche directement dans le terminal courant. Appuyez sur `q` ou `Q` pour quitter proprement. La TUI s'affiche directement dans le terminal courant. Appuyez sur `q` ou `Q` pour quitter proprement.

6
include/lardon3d/app.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef LARDON3D_APP_H
#define LARDON3D_APP_H
int lardon3d_app_run(void);
#endif

View file

@ -0,0 +1,8 @@
#ifndef LARDON3D_LAYOUT_H
#define LARDON3D_LAYOUT_H
#include <stdbool.h>
bool lardon3d_layout_draw(void);
#endif

10
include/lardon3d/tui.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef LARDON3D_TUI_H
#define LARDON3D_TUI_H
#include <stdbool.h>
bool lardon3d_tui_init(void);
bool lardon3d_tui_run(void);
void lardon3d_tui_shutdown(void);
#endif

View file

@ -1,14 +0,0 @@
#ifndef SCAN3D_APP_H
#define SCAN3D_APP_H
#ifdef __cplusplus
extern "C" {
#endif
int scan3d_app_run(void);
#ifdef __cplusplus
}
#endif
#endif /* SCAN3D_APP_H */

View file

@ -1,18 +0,0 @@
#ifndef SCAN3D_TUI_H
#define SCAN3D_TUI_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
bool scan3d_tui_init(void);
bool scan3d_tui_run(void);
void scan3d_tui_shutdown(void);
#ifdef __cplusplus
}
#endif
#endif /* SCAN3D_TUI_H */

View file

@ -1,5 +1,5 @@
project( project(
'scan3d-vulkan', 'lardon3d',
'c', 'c',
version: '0.1.0', version: '0.1.0',
license: 'MIT', license: 'MIT',
@ -20,11 +20,12 @@ add_project_arguments(
ncursesw = dependency('ncursesw', required: true) ncursesw = dependency('ncursesw', required: true)
executable( executable(
'scan3d-vulkan', 'lardon3d',
sources: [ sources: [
'src/main.c', 'src/main.c',
'src/app.c', 'src/app.c',
'src/tui.c', 'src/tui.c',
'src/layout.c',
], ],
include_directories: include_directories('include'), include_directories: include_directories('include'),
dependencies: [ncursesw], dependencies: [ncursesw],

View file

@ -1,17 +1,22 @@
#include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <scan3d/app.h> #include <lardon3d/app.h>
#include <scan3d/tui.h> #include <lardon3d/tui.h>
int int
scan3d_app_run(void) lardon3d_app_run(void)
{ {
if (!scan3d_tui_init()) { if (!setlocale(LC_ALL, "")) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
bool success = scan3d_tui_run(); if (!lardon3d_tui_init()) {
scan3d_tui_shutdown(); return EXIT_FAILURE;
}
bool success = lardon3d_tui_run();
lardon3d_tui_shutdown();
return success ? EXIT_SUCCESS : EXIT_FAILURE; return success ? EXIT_SUCCESS : EXIT_FAILURE;
} }

106
src/layout.c Normal file
View file

@ -0,0 +1,106 @@
#include <ncurses.h>
#include <stdbool.h>
#include <string.h>
#include <lardon3d/layout.h>
enum {
MINIMUM_ROWS = 20,
MINIMUM_COLUMNS = 72,
};
static void
draw_text(int row, int column, int available, const char *text)
{
if (available <= 0) {
return;
}
size_t length = strlen(text);
int displayed = length < (size_t)available ? (int)length : available;
(void)mvaddnstr(row, column, text, displayed);
}
static void
draw_too_small(int rows, int columns)
{
static const char message[] = "Terminal trop petit";
int row = rows > 0 ? rows / 2 : 0;
int column = columns > (int)(sizeof(message) - 1)
? (columns - (int)(sizeof(message) - 1)) / 2
: 0;
draw_text(row, column, columns, message);
}
static void
draw_frame(int rows, int columns)
{
int middle_column = columns / 2;
int journal_row = rows / 2;
int footer_row = rows - 3;
(void)box(stdscr, 0, 0);
(void)mvhline(2, 1, ACS_HLINE, columns - 2);
(void)mvhline(journal_row, 1, ACS_HLINE, columns - 2);
(void)mvhline(footer_row, 1, ACS_HLINE, columns - 2);
(void)mvvline(3, middle_column, ACS_VLINE, journal_row - 3);
(void)mvaddch(2, 0, ACS_LTEE);
(void)mvaddch(2, middle_column, ACS_TTEE);
(void)mvaddch(2, columns - 1, ACS_RTEE);
(void)mvaddch(journal_row, 0, ACS_LTEE);
(void)mvaddch(journal_row, middle_column, ACS_BTEE);
(void)mvaddch(journal_row, columns - 1, ACS_RTEE);
(void)mvaddch(footer_row, 0, ACS_LTEE);
(void)mvaddch(footer_row, columns - 1, ACS_RTEE);
}
static void
draw_content(int rows, int columns)
{
int middle_column = columns / 2;
int journal_row = rows / 2;
draw_text(1, 2, middle_column - 3, "Lardon3D");
draw_text(1, columns - 7, 5, "Heure");
draw_text(3, 2, middle_column - 3, "Projet");
draw_text(5, 4, middle_column - 5, "Aucun projet chargé.");
draw_text(3, middle_column + 2, columns - middle_column - 3, "Informations");
draw_text(5, middle_column + 4, columns - middle_column - 5, "Lardon3D");
draw_text(6, middle_column + 4, columns - middle_column - 5, "Reconstruction 3D");
draw_text(7, middle_column + 4, columns - middle_column - 5, "Version 0.1");
draw_text(journal_row + 1, 2, columns - 4, "Journal");
draw_text(journal_row + 3, 4, columns - 6, "Bienvenue dans Lardon3D");
draw_text(
rows - 2,
2,
columns - 4,
"F1 Aide F2 Projet F3 Import F4 Viewer Q Quit"
);
}
bool
lardon3d_layout_draw(void)
{
int rows;
int columns;
getmaxyx(stdscr, rows, columns);
if (erase() == ERR) {
return false;
}
if (rows < MINIMUM_ROWS || columns < MINIMUM_COLUMNS) {
draw_too_small(rows, columns);
} else {
draw_frame(rows, columns);
draw_content(rows, columns);
}
return refresh() != ERR;
}

View file

@ -1,7 +1,7 @@
#include <scan3d/app.h> #include <lardon3d/app.h>
int int
main(void) main(void)
{ {
return scan3d_app_run(); return lardon3d_app_run();
} }

View file

@ -1,59 +1,11 @@
#include <ncurses.h> #include <ncurses.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <scan3d/tui.h> #include <lardon3d/layout.h>
#include <lardon3d/tui.h>
static void
draw_centered(int row, int rows, int columns, const char *text)
{
if (row < 0 || row >= rows || columns <= 2) {
return;
}
int length = (int)strlen(text);
int available = columns - 2;
int displayed = length < available ? length : available;
int column = (columns - displayed) / 2;
(void)mvaddnstr(row, column, text, displayed);
}
static bool
draw_interface(void)
{
int rows;
int columns;
getmaxyx(stdscr, rows, columns);
if (erase() == ERR) {
return false;
}
if (rows >= 2 && columns >= 2) {
(void)box(stdscr, 0, 0);
}
draw_centered(1, rows, columns, "Scan3D Vulkan");
draw_centered(3, rows, columns, "Projet de reconstruction 3D");
char dimensions[64];
(void)snprintf(
dimensions,
sizeof(dimensions),
"Terminal : %d x %d",
columns,
rows
);
draw_centered(5, rows, columns, dimensions);
draw_centered(rows - 2, rows, columns, "q : quitter");
return refresh() != ERR;
}
bool bool
scan3d_tui_init(void) lardon3d_tui_init(void)
{ {
if (!initscr()) { if (!initscr()) {
return false; return false;
@ -69,9 +21,9 @@ scan3d_tui_init(void)
} }
bool bool
scan3d_tui_run(void) lardon3d_tui_run(void)
{ {
if (!draw_interface()) { if (!lardon3d_layout_draw()) {
return false; return false;
} }
@ -83,14 +35,14 @@ scan3d_tui_run(void)
if (key == ERR) { if (key == ERR) {
return false; return false;
} }
if (key == KEY_RESIZE && !draw_interface()) { if (key == KEY_RESIZE && !lardon3d_layout_draw()) {
return false; return false;
} }
} }
} }
void void
scan3d_tui_shutdown(void) lardon3d_tui_shutdown(void)
{ {
endwin(); endwin();
} }