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.
@ -22,7 +22,7 @@ meson compile -C build -j8
## Exécution
```sh
./build/scan3d-vulkan
./build/lardon3d
```
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(
'scan3d-vulkan',
'lardon3d',
'c',
version: '0.1.0',
license: 'MIT',
@ -20,11 +20,12 @@ add_project_arguments(
ncursesw = dependency('ncursesw', required: true)
executable(
'scan3d-vulkan',
'lardon3d',
sources: [
'src/main.c',
'src/app.c',
'src/tui.c',
'src/layout.c',
],
include_directories: include_directories('include'),
dependencies: [ncursesw],

View file

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

View file

@ -1,59 +1,11 @@
#include <ncurses.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <scan3d/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;
}
#include <lardon3d/layout.h>
#include <lardon3d/tui.h>
bool
scan3d_tui_init(void)
lardon3d_tui_init(void)
{
if (!initscr()) {
return false;
@ -69,9 +21,9 @@ scan3d_tui_init(void)
}
bool
scan3d_tui_run(void)
lardon3d_tui_run(void)
{
if (!draw_interface()) {
if (!lardon3d_layout_draw()) {
return false;
}
@ -83,14 +35,14 @@ scan3d_tui_run(void)
if (key == ERR) {
return false;
}
if (key == KEY_RESIZE && !draw_interface()) {
if (key == KEY_RESIZE && !lardon3d_layout_draw()) {
return false;
}
}
}
void
scan3d_tui_shutdown(void)
lardon3d_tui_shutdown(void)
{
endwin();
}