Skip to content
Snippets Groups Projects
Commit dbf8342a authored by thibault.capt's avatar thibault.capt
Browse files

Merge branch 'GUI' into 'main'

Tui

See merge request !1
parents 668150b8 1561033f
No related branches found
No related tags found
1 merge request!1Tui
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/training-session.iml" filepath="$PROJECT_DIR$/.idea/training-session.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cursive = "0.19.0"
\ No newline at end of file
/// Importer le module `Training` depuis le fichier externe
use crate::training::Training;
/// Importations des bibliothèques standard et de cursive
use std::rc::Rc;
use cursive::Cursive;
use cursive::{
views::{Button, Dialog, DummyView, EditView, LinearLayout, SelectView, TextView, NamedView, ResizedView},
traits::*,
};
/// Fonction publique pour générer le TUI
pub fn run() {
// Initialisation de Cursive
let mut siv = cursive::default();
// Vue des entraînements
let select = SelectView::<Training>::new()
.on_submit(on_submit) // Appelé lors de la soumission de la sélection
.with_name("select") // Nom de la vue
.fixed_size((10, 5)); // Taille fixe de la vue
// Buttons pour ajouter et supprimer un entraînement
let buttons = LinearLayout::vertical()
.child(Button::new("Add new", add_training)) // Bouton pour ajouter un nouvel entraînement
.child(Button::new("Delete", delete_training)) // Bouton pour supprimer un entraînement
.child(DummyView) // Vue fictive pour ajouter de l'espace
.child(Button::new("Quit", Cursive::quit)); // Bouton pour quitter l'application
// Ajout de la couche de dialogue principale à Cursive
siv.add_layer(Dialog::around(LinearLayout::horizontal()
.child(select) // Ajout de la vue de sélection
.child(DummyView) // Ajout d'espace vide
.child(buttons)) // Ajout des boutons
.title("Select a training")); // Titre de la couche de dialogue
// Exécution de la boucle principale de Cursive
siv.run();
}
/// Fonction interne pour gérer l'ajout d'un nouvel entraînement
///
/// # Arguments
///
/// * `s` - Une référence mutable à Cursive
fn add_training(s: &mut Cursive) {
fn ok(s: &mut Cursive, training: Training) {
// Ajout de l'entraînement à la vue de sélection
s.call_on_name("select", |view: &mut SelectView<Training>| {
view.add_item(training.name.clone(), training.clone()); // Using the cloned_training
});
s.pop_layer(); // Fermer la couche de dialogue
}
// Ajout d'une couche de dialogue pour l'ajout d'un nouvel entraînement
s.add_layer(Dialog::around(
LinearLayout::vertical()
.with(
|list| for item in Training::TRAINING_ITEMS.iter() {
list.add_child(create_label(item)); // Ajout d'un label pour chaque élément de l'entraînement
list.add_child(create_edit_view(item)); // Ajout d'un champ de saisie pour chaque élément
list.add_child(DummyView); // Ajout d'espace vide
})
.child(DummyView) // Ajout d'espace vide
.child(LinearLayout::horizontal()
.child(Button::new(
"Ok", |s| { // Bouton "Ok" pour valider l'ajout
// Récupération des données saisies par l'utilisateur
let name = get_view_content(s, "name");
let description = get_view_content(s, "description");
let date = get_view_content(s, "date");
let location = get_view_content(s, "location");
let duration = get_view_content(s, "duration").parse::<i32>().unwrap_or(0);
let participants_str = get_view_content(s, "participants").to_string();
let participants = participants_str.split(",").map(str::trim).collect();
// Vérification si le nom est vide
if name.is_empty() {
s.add_layer(Dialog::info("Name cannot be empty")); // Affichage d'un message d'erreur
} else {
ok(s, Training::new(&name, &description, &date, &location, duration, participants)); // Appel de la fonction `ok` pour gérer l'ajout
}
}))
.child(Button::new("Cancel", |s| {
s.pop_layer(); // Annuler l'ajout et fermer la couche de dialogue
}))))
.title("Enter a new training") // Titre de la couche de dialogue
.scrollable() // Permettre le défilement si le contenu dépasse
);
}
/// Récupérer le contenu de la vue
///
/// # Arguments
///
/// * `s` - Une référence mutable à Cursive
/// * `name` - Le nom du champ de saisie
fn get_view_content(s: &mut Cursive, name: &str) -> Rc<String> {
s.call_on_name(name, |view: &mut EditView| view.get_content()).unwrap()
}
/// Créer un label pour un champ de l'entraînement
///
/// # Arguments
///
/// * `name` - Le nom du champ
fn create_label(name: &str) -> NamedView<TextView> {
TextView::new(format!("{}:", name)).with_name(format!("{}_label", &name))
}
/// Créer un champ de saisie pour un champ de l'entraînement
///
/// # Arguments
///
/// * `name` - Le nom du champ
fn create_edit_view(name: &str) -> ResizedView<NamedView<EditView>> {
EditView::new()
.with_name(name)
.fixed_width(18)
}
/// Supprimer un entraînement
///
/// # Arguments
///
/// * `s` - Une référence mutable à Cursive
fn delete_training(s: &mut Cursive) {
let mut select = s.find_name::<SelectView<Training>>("select").unwrap(); // Trouver la vue de sélection
match select.selected_id() {
None => s.add_layer(Dialog::info("No train to remove")), // Afficher un message s'il n'y a pas de formation sélectionnée
Some(focus) => {
select.remove_item(focus); // Supprimer l'entraînement sélectionnée
}
}
}
/// Appelé lorsque l'utilisateur soumet un entraînement
///
/// # Arguments
///
/// * `s` - Une référence mutable à Cursive
/// * `training` - Une référence à la structure Training soumise
fn on_submit(s: &mut Cursive, training: &Training) {
// Afficher les informations de l'entraînement dans une couche de dialogue
s.add_layer(Dialog::text(training.to_string())
.title(format!("{}'s info", training.name)) // Titre de la couche de dialogue
.button("Quit", |s| {
s.pop_layer(); // Ajouter un bouton pour fermer la couche de dialogue
})
.scrollable() // Permettre le défilement si le contenu dépasse
);
}
\ No newline at end of file
/// Module de l'application
mod app;
/// Module pour la gestion de l'entraînement
mod training;
fn main() {
println!("Hello, world!");
app::run();
}
\ No newline at end of file
/// Structure représentant un entraînement
#[derive(Clone)]
pub struct Training {
/// Nom de l'entraînement
pub name: String,
/// Description de l'entraînement
pub description: String,
/// Date de l'entraînement
pub date: String,
/// Lieu de l'entraînement
pub location: String,
/// Durée de l'entraînement en heures
pub duration: i32,
/// Liste des participants à l'entraînement
pub participants: Vec<String>,
}
impl Training {
/// Tableau des éléments de l'entraînement
pub const TRAINING_ITEMS: [&'static str; 6] = ["name", "description", "date", "location", "duration", "participants"];
/// Crée une nouvelle instance de la structure Training
///
/// # Arguments
///
/// * `name` - Le nom de l'entraînement
/// * `description` - La description de l'entraînement
/// * `date` - La date de l'entraînement
/// * `location` - Le lieu de l'entraînement
/// * `duration` - La durée de l'entraînement en heures
/// * `participants` - Les participants à l'entraînement sous forme de vecteur de chaînes de caractères
pub fn new(
name: &str,
description: &str,
date: &str,
location: &str,
duration: i32,
participants: Vec<&str>
) -> Training {
Training {
name: name.to_string(),
description: description.to_string(),
date: date.to_string(),
location: location.to_string(),
duration,
participants: participants.iter().map(ToString::to_string).collect(),
}
}
/// Convertit la structure Training en une chaîne de caractères formatée
pub fn to_string(&self) -> String {
format!("Name: {}\nDescription: {}\nDate: {}\nLocation: {}\nDuration: {}\nParticipants: {}",
self.name, self.description, self.date, self.location, self.duration.to_string(), self.participants.join(","))
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment