copie SAE papillon

This commit is contained in:
2025-10-26 22:42:53 +01:00
commit 65aad15997
31 changed files with 35634 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
# ---> Java
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*

Binary file not shown.

Binary file not shown.

33080
Documentations/Rapports.pdf Normal file

File diff suppressed because it is too large Load Diff

71
Makefile Normal file
View File

@@ -0,0 +1,71 @@
# === Global variables ===
MAIN_CLASS = fr.iutfbleau.papillon.Start
BUILD_DIR = build
SRC_DIR = src/fr/iutfbleau/papillon
SRC_BUILD = fr\iutfbleau\papillon
LIB_DIR := lib
LIB := $(LIB_DIR)/mariadb
JAR_NAME = papillon.jar
DOC_DIR = doc
# === OS detection ===
ifeq ($(OS),Windows_NT)
SEP = ;
RM = del /Q
RMDIR = rmdir /S /Q
else
SEP = :
RM = rm -f
RMDIR = rm -rf
endif
# === Compilation ===
compile:
@echo === Compilation du projet ===
javac -encoding UTF-8 -cp "$(LIB_DIR)$(SEP)$(LIB_DIR)/org/mariadb/jdbc" -d $(BUILD_DIR) $(SRC_DIR)/*.java
@echo Compilation terminee
# === Run the program ===
run:
@echo === Execution du programme ===
ifeq ($(OS),Windows_NT)
java -cp "$(BUILD_DIR);$(LIB_DIR);$(LIB_DIR)/mariadb;$(LIB_DIR)/mariadb/org/mariadb/jdbc" $(MAIN_CLASS)
else
java -cp "$(BUILD_DIR):$(LIB_DIR):$(LIB_DIR)/mariadb:$(LIB_DIR)/mariadb/org/mariadb/jdbc" $(MAIN_CLASS)
endif
# === Create JAR ===
jar: compile
@echo === Creation du JAR autonome ===
echo Main-Class: $(MAIN_CLASS) > manifest.txt
jar cfm $(JAR_NAME) manifest.txt -C $(BUILD_DIR) .
@$(RM) manifest.txt 2>nul || true
@echo JAR cree avec succes: $(JAR_NAME)
# === Run from JAR ===
run-jar:
@echo === Execution du JAR ===
ifeq ($(OS),Windows_NT)
java -cp "$(JAR_NAME);$(LIB_DIR);$(LIB_DIR)/mariadb;$(LIB_DIR)/mariadb/org/mariadb/jdbc" $(MAIN_CLASS)
else
java -cp "$(JAR_NAME):$(LIB_DIR):$(LIB_DIR)/mariadb:$(LIB_DIR)/mariadb/org/mariadb/jdbc" $(MAIN_CLASS)
endif
# === Generate documentation ===
doc:
@echo === Generation de la documentation Javadoc ===
javadoc -d $(DOC_DIR) -encoding UTF-8 -cp "$(LIB_DIR)$(SEP)$(LIB_DIR)/org/mariadb/jdbc" $(SRC_DIR)/*.java
@echo Documentation generee dans le dossier doc/
# === Clean build and docs ===
clean:
@echo === Nettoyage des fichiers compiles ===
ifeq ($(OS),Windows_NT)
$(RM) $(BUILD_DIR)\$(SRC_BUILD)\*.class 2>nul || true
for /d %%i in ($(DOC_DIR)\*) do rmdir /S /Q "%%i" 2>nul || true
$(RM) $(DOC_DIR)\* 2>nul || true
else
$(RM) $(BUILD_DIR)/fr/iutfbleau/papillon/*.class
find $(DOC_DIR) -mindepth 1 -delete 2>/dev/null || true
endif
@echo Nettoyage termine

137
README.md Normal file
View File

@@ -0,0 +1,137 @@
# Papillon 🦋
Bienvenue sur notre projet **"PAPILLON"**, un logiciel qui reste en permanence au premier plan, comme un papillon collé sur le moniteur. Ce projet a été réalisé dans le cadre de la [SAÉ 3.1](https://iut-fbleau.fr/sitebp/sae3/31_2025/Y8R8E4MV9Y7T33O8.php) de l'IUT Sénart-Fontainebleau.
## Table des matières
- [Présentation](#présentation)
- [Organisation du projet](#organisation-du-projet)
- [Compilation et lancement](#Compilation-et-lancement)
- [Création de la documentation](#création-de-la-documentation)
- [Nettoyage des fichiers temporaires](#Nettoyage-des-fichiers-temporaires)
- [Rapport d'avancement](#Rapport-d-avancement)
- [Crédits](#crédits)
---
## Présentation
Papillon, est une application de gestion de rappels qui permet à l'utilisateur :
- D'ajouter des rappels (titre, contenu, thème, rang).
- De modifier ou supprimer un rappel existant.
- De consulter la liste de tous ses rappels.
- Et d'avoir la fenêtre visible (comme un papillon posé sur l'écran).
Ce projet a été développé en **Java** en suivant les consignes de lIUT afin dassurer une structure claire et un code facile à maintenir.
---
## Organisation du projet
Lorganisation du projet suit une structure claire permettant de séparer le code source, les composants externes et les fichiers de configuration. Voici l'aborescence :
```
SAE31_2025/
├── Documentations/
│ ├── Diagrammes/
│ └── Rapports.pdf
├── lib/ # Bibliothèques externes MariaDB
├── src/ # Code source du projet
│ └── fr/iutbleau/papillon/ # Package principal contenant toutes les classes Java
│ ├── BaseDeDonnees.java
│ ├── BtnAjouter.java
│ ├── BtnModifier.java
│ ├── BtnSupprimer.java
│ ├── ChoixRang.java
│ ├── ColorIcon.java
│ ├── CouleurList.java
│ ├── Crud.java
│ ├── FenetreAjout.java
│ ├── FenetreModif.java
│ ├── FenetreRappel.java
│ ├── GestionAjout.java
│ ├── GestionModif.java
│ ├── GestionRappel.java
│ ├── LimiteContenu.java
│ ├── Main.java
│ ├── PanelRappel.java
│ ├── Rappel.java
│ ├── RappelBD.java
│ ├── Start.java
│ ├── UserKey.java
│ ├── Utilisateur.java
│ └── UtilisateurBD.java
├── .gitignore # Permet dignorer les fichiers .class générés lors de la compilation
├── Makefile # Automatisation pour la compilation et lexécution
├── README.md # Fichier actuelle
└── logo.png #Logo de la fenêtre
```
---
## Compilation et lancement
# Pré-requis
- **MariaDB client** (inclus dans le répertoire `libs`)
---
Pour avoir accès au projet faire les commandes suivantes:
```bash
# Cloner le dépôt
git clone https://grond.iut-fbleau.fr/yolou/SAE31_2025/
cd SAE31_2025
```
Pour compile et exécuter
```bash
# Compiler et exécuter le projet
make compile
make run
```
ou
### Création du fichier `.jar`
Vous pouvez générer une archive exécutable :
```bash
make jar
```
Avec l'archive .jar on exécute :
```bash
make run-jar
```
---
## Création de la documentation
La documentation du code source est générée via **Javadoc**. Utilisez :
```bash
make doc
```
---
## Nettoyage des fichiers temporaires
Pour supprimer les fichiers intermédiaires on fait :
```bash
make clean
```
---
## Rapport d'avancement
Le rapport du projet est disponible dans le dossier `Documentation`. Accédez-y directement ici : [Documentations/Rapport.pdf](./Documentations/Rapports.pdf).
---
## Crédits
Ce projet a été réalisé par :
- [Jenson VAL](https://grond.iut-fbleau.fr/val)
- [Aylane SEHL](https://grond.iut-fbleau.fr/sehl)
- [Séri-Khane YOLOU](https://grond.iut-fbleau.fr/yolou)
Professeur : **Luc Hernandez**.

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

View File

@@ -0,0 +1,40 @@
package fr.iutfbleau.papillon;
import java.sql.*;
/**
* La classe <code>BaseDeDonnees</code> fournit les paramètres et méthodes
* nécessaires à létablissement dune connexion à la base MariaDB.
*
* <p>Elle centralise les informations de connexion (URL, utilisateur et mot de passe)
* et renvoie un objet {@link java.sql.Connection} pour exécuter les requêtes SQL.</p>
*
* @version 1.0
* @author Seri-khane Yolou, Aylane SEHL, Jenson VAL
*/
public class BaseDeDonnees {
/** URL de connexion à la base de données MariaDB. */
private static final String URL = "jdbc:mariadb://dwarves.iut-fbleau.fr/yolou";
/** Nom dutilisateur pour la base de données. */
private static final String USER = "yolou";
/** Mot de passe associé à lutilisateur. */
private static final String PASS = "serikhaneyolou";
/**
* Établit une connexion avec la base de données MariaDB.
*
* @return un objet {@link java.sql.Connection} actif vers la base
* @throws SQLException si une erreur survient lors de la connexion
*/
public static java.sql.Connection getConnexion() throws SQLException {
try {
Class.forName("org.mariadb.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("Erreur : pilote MariaDB non trouvé !");
}
return DriverManager.getConnection(URL, USER, PASS);
}
}

View File

@@ -0,0 +1,66 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
/**
* La classe <code>BtnAjouter</code> représente un bouton permettant
* douvrir la fenêtre dajout dun nouveau rappel dans lapplication <b>Papillon</b>.
* <p>
* Lorsquun utilisateur clique sur ce bouton, une instance de la fenêtre
* <code>FenetreAjout</code> est affichée, tandis que la fenêtre principale est masquée.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class BtnAjouter extends JButton implements ActionListener{
/**
* Référence vers la fenêtre principale de lapplication.
* Elle permet de gérer la visibilité des fenêtres lors de lajout dun rappel.
*/
private Main main;
/**
* Construit un bouton "Ajouter" associé à la fenêtre principale.
* <p>
* Ce bouton est configuré avec une taille fixe et un écouteur daction
* pour réagir aux clics de lutilisateur.
* </p>
*
* @param main la fenêtre principale de lapplication <b>Papillon</b>
*/
public BtnAjouter(Main main){
super("Ajouter");
this.main = main;
setPreferredSize(new Dimension(120,25));
setFocusPainted(false);
addActionListener(this);
}
/**
* Méthode appelée lorsquun clic est détecté sur le bouton.
* <p>
* Ouvre une nouvelle fenêtre dajout (<code>FenetreAjout</code>),
* positionnée au même endroit que la fenêtre principale, puis
* masque cette dernière.
* </p>
*
* @param e lévénement daction généré par le clic sur le bouton
*/
@Override
public void actionPerformed(ActionEvent e){
if(e.getSource()==this){
FenetreAjout f = new FenetreAjout(main);
f.setLocation(main.getLocation());
f.setVisible(true);
main.setVisible(false);
}
}
}

View File

@@ -0,0 +1,93 @@
package fr.iutfbleau.papillon;
import java.util.ArrayList;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.List;
/**
* La classe <code>BtnModifier</code> représente un bouton permettant
* de modifier un rappel existant dans lapplication <b>Papillon</b>.
* <p>
* Lorsquun utilisateur clique sur ce bouton, il vérifie quun seul rappel
* est sélectionné. Si cest le cas, la fenêtre de modification
* (<code>FenetreModif</code>) souvre pour permettre à lutilisateur
* de modifier les informations du rappel choisi.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class BtnModifier extends JButton implements ActionListener {
/**
* Référence vers le rappel actuellement sélectionné.
*/
private Rappel rappel;
/**
* Référence vers la fenêtre principale de lapplication.
* Elle permet de gérer la visibilité des fenêtres lors de la modification dun rappel.
*/
private final Main main;
/**
* Construit un bouton "Modifier" associé à la fenêtre principale.
* <p>
* Ce bouton est configuré avec une taille fixe et un écouteur daction
* pour réagir aux clics de lutilisateur.
* </p>
*
* @param main la fenêtre principale de lapplication <b>Papillon</b>
*/
public BtnModifier(Main main) {
super("Modifier");
this.main = main;
setPreferredSize(new Dimension(120, 25));
addActionListener(this);
setFocusPainted(false);
}
@Override
public void actionPerformed(ActionEvent e){
if (e.getSource() == this) {
int count = 0;
List<PanelRappel> listRpl = new ArrayList<>();
PanelRappel pr;
listRpl = main.getPanelRpl();
for(int i = 0; i<listRpl.size();i++){
pr = listRpl.get(i);
if(pr.getSelection()==true){
count++;
rappel=pr.getRappel();
}
}
if(count==0){
JOptionPane.showMessageDialog(main, "Sélectionnez 1 rappel à modifier");
return;
}
if(count==1){
FenetreModif f = new FenetreModif(main,rappel);
f.setVisible(true);
main.dispose();
}
if(count>1){
JOptionPane.showMessageDialog(main, "Sélectionnez seulement 1 rappel à modifier");
return;
}
return;
}
}
}

View File

@@ -0,0 +1,109 @@
package fr.iutfbleau.papillon;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* La classe <code>BtnSupprimer</code> représente un bouton permettant
* de supprimer un ou plusieurs rappels dans lapplication <b>Papillon</b>.
* <p>
* Lorsquun utilisateur clique sur ce bouton, une boîte de confirmation
* saffiche afin de valider la suppression. Si lutilisateur confirme,
* les rappels sélectionnés sont supprimés de la liste.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class BtnSupprimer extends JButton implements ActionListener{
/**
* Gestionnaire des rappels permettant deffectuer la suppression.
*/
private GestionRappel ges;
/**
* Référence vers la fenêtre principale de lapplication.
* Elle permet de gérer la visibilité des fenêtres lors de la suppression dun rappel.
*/
private Main main;
/**
* Construit un bouton "Supprimer" associé à la fenêtre principale.
* <p>
* Ce bouton est configuré avec une taille fixe et un écouteur daction
* pour réagir aux clics de lutilisateur.
* </p>
*
* @param main la fenêtre principale de lapplication <b>Papillon</b>
*/
public BtnSupprimer(Main main){
super("Supprimer");
this.main = main;
setPreferredSize(new Dimension(120,25));
addActionListener(this);
setFocusPainted(false);
}
/**
* Gère laction effectuée lors dun clic sur le bouton.
* <p>
* Si aucun rappel nest sélectionné, un message davertissement est affiché.
* Sinon, une boîte de dialogue de confirmation souvre avant de procéder
* à la suppression des rappels choisis.
* </p>
*
* @param e lévénement daction déclenché par un clic
*/
@Override
public void actionPerformed(ActionEvent e){
if(e.getSource()==this){
ges = new GestionRappel();
int count = 0;
List<PanelRappel> listRpl = new ArrayList<>();
PanelRappel pr;
listRpl = main.getPanelRpl();
for(int i = 0; i<listRpl.size();i++){
pr = listRpl.get(i);
if(pr.getSelection()==true){
count++;
}
}
if(count==0){
JOptionPane.showMessageDialog(main, "Sélectionnez les rappels que vous souhaiter supprimer !");
}else{
int choix = JOptionPane.showConfirmDialog(
main,
"Êtes-vous sûr de vouloir supprimer ce(s) rappel(s) ?",
"Confirmation",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (choix == JOptionPane.YES_OPTION) {
for(int i = 0; i<listRpl.size();i++){
pr = listRpl.get(i);
if(pr.getSelection()==true){
try{
ges.supprimerParId(pr.getId());
} catch (Exception ex) {
ex.printStackTrace(); // affiche l'erreur dans le terminal
}
}
}
JOptionPane.showMessageDialog(main, "Les rappels on bien étaient supprimé.");
new Main().setVisible(true);
main.dispose();
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
/**
* La classe <code>ChoixRang</code> représente une liste déroulante
* permettant de filtrer les rappels selon leur niveau de priorité (rang)
* dans lapplication <b>Papillon</b>.
* <p>
* Lutilisateur peut sélectionner un rang spécifique ou choisir “Tout”
* pour afficher tous les rappels.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class ChoixRang extends JComboBox<String> {
/**
* Constructeur qui initialise la liste déroulante des rangs.
* <p>
* Par défaut, lélément sélectionné est “Tout”.
* </p>
*/
public ChoixRang(){
super(new String[]{"Tout", "Rang 1", "Rang 2", "Rang 3","Rang 4", "Rang 5"});
this.setSelectedItem("Tout");
this.addActionListener(this);
}
/**
* Met à jour laffichage des rappels en fonction du rang sélectionné.
*
* @param main la fenêtre principale de lapplication <b>Papillon</b>
*/
public void tirage(Main main){
main.setTrie(this.getSelectedIndex());
main.maj();
}
}

View File

@@ -0,0 +1,78 @@
package fr.iutfbleau.papillon;
import javax.swing.Icon;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
/**
* La classe <code>ColorIcon</code> permet dafficher un petit carré coloré
* servant dicône dans linterface de lapplication <b>Papillon</b>.
* <p>
* Elle est utilisée notamment pour représenter visuellement un thème de couleur
* associé à un rappel ou un élément dinterface.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class ColorIcon implements Icon {
/** Couleur à afficher dans licône. */
private final Color couleur;
/** Largeur de licône. */
private final int largeur;
/** Hauteur de licône. */
private final int hauteur;
/**
* Constructeur de licône colorée.
*
* @param couleur la couleur de licône
* @param largeur la largeur de licône
* @param hauteur la hauteur de licône
*/
public ColorIcon(Color couleur, int largeur, int hauteur) {
this.couleur = couleur;
this.largeur = largeur;
this.hauteur = hauteur;
}
/**
* Renvoie la largeur de licône.
*
* @return la largeur de licône
*/
@Override
public int getIconWidth() {
return largeur;
}
/**
* Renvoie la hauteur de licône.
*
* @return la hauteur de licône
*/
@Override
public int getIconHeight() {
return hauteur;
}
/**
* Dessine licône sur le composant spécifié.
*
* @param c le composant sur lequel licône est dessinée
* @param g le contexte graphique utilisé pour le dessin
* @param x la position horizontale du coin supérieur gauche
* @param y la position verticale du coin supérieur gauche
*/
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(couleur);
g.fillRect(x, y, largeur, hauteur);
g.setColor(Color.DARK_GRAY);
g.drawRect(x, y, largeur - 1, hauteur - 1);
}
}

View File

@@ -0,0 +1,60 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
/**
* La classe <code>CouleurList</code> permet dafficher des couleurs
* associées à des thèmes dans les listes déroulantes de lapplication <b>Papillon</b>.
* <p>
* Elle agit comme un <b>renderer</b> personnalisé, affichant un petit carré coloré
* à côté du nom du thème.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class CouleurList extends DefaultListCellRenderer {
/**
* Renvoie la couleur correspondant au nom affiché dans le menu déroulant.
*
* @param nom le nom du thème (ex. : "Bleu", "Rouge", "Vert", etc.)
* @return la couleur associée au thème, ou blanc par défaut
*/
public Color couleurDe(String nom) {
switch (nom) {
case "Bleu": return Color.CYAN;
case "Rouge": return Color.RED;
case "Vert": return Color.GREEN;
case "Jaune": return Color.YELLOW;
case "Rose": return Color.PINK;
default: return Color.WHITE;
}
}
/**
* Personnalise laffichage des éléments dans la liste déroulante.
*
* @param list la liste affichant les éléments
* @param value lélément à afficher
* @param index lindice de lélément dans la liste
* @param isSelected indique si lélément est sélectionné
* @param cellHasFocus indique si lélément a le focus
* @return le composant personnalisé pour laffichage de lélément
*/
@Override
public JLabel getListCellRendererComponent(JList list, Object value, int index,boolean isSelected, boolean cellHasFocus) {
JLabel lbl = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value != null) {
String nom = value.toString();
lbl.setIcon(new ColorIcon(couleurDe(nom), 14, 14));
lbl.setIconTextGap(8); // petit espace entre le carré et le texte
}
return lbl;
}
}

View File

@@ -0,0 +1,48 @@
package fr.iutfbleau.papillon;
import java.util.ArrayList;
import javax.swing.*;
/**
* La classe <code>Crud</code> regroupe les trois boutons principaux
* de gestion des rappels dans lapplication <b>Papillon</b> :
* <ul>
* <li><b>Ajouter</b> — pour créer un nouveau rappel,</li>
* <li><b>Supprimer</b> — pour supprimer un ou plusieurs rappels,</li>
* <li><b>Modifier</b> — pour éditer un rappel existant.</li>
* </ul>
* <p>
* Cette classe centralise leur création et leur ajout à linterface.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class Crud extends ArrayList<JButton>{
/** Bouton dajout de rappel. */
private BtnAjouter btnAjt;
/** Bouton de suppression de rappel. */
private BtnSupprimer btnSpr;
/** Bouton de modification de rappel. */
private BtnModifier btnMdf;
/**
* Constructeur de la barre dactions CRUD.
*
* @param main la fenêtre principale de lapplication <b>Papillon</b>
*/
public Crud(Main main){
btnAjt = new BtnAjouter(main);
btnSpr = new BtnSupprimer(main);
btnMdf = new BtnModifier(main);
add(btnAjt);
add(btnSpr);
add(btnMdf);
}
}

View File

@@ -0,0 +1,135 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
/**
* La classe <code>FenetreAjout</code> permet dafficher une fenêtre
* dédiée à lajout dun nouveau rappel dans lapplication <b>Papillon</b>.
* <p>
* Elle contient les champs nécessaires à la saisie du titre, du contenu,
* de la priorité et du thème du rappel.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class FenetreAjout extends JFrame {
/** Champ de saisie pour le titre du rappel. */
private final JTextField champTitre;
/** Champ de saisie pour le contenu du rappel. */
private final JTextArea champContenu;
/** Liste de niveaux de priorité disponibles. */
private Integer[] nombres = {1, 2, 3, 4, 5};
/** Sélecteur du niveau de priorité. */
private JComboBox<Integer> rang = new JComboBox<>(nombres);
/** Liste des noms de thèmes disponibles. */
private final String[] nomsCouleurs = {"Bleu", "Rouge", "Vert", "Jaune", "Rose"};
/** Sélecteur du thème du rappel. */
private final JComboBox<String> comboTheme = new JComboBox<>(nomsCouleurs);
/** Gestionnaire des boutons d'ajout. */
private GestionAjout listBtnAjout;
/**
* Constructeur de la fenêtre dajout.
*
* @param parent la fenêtre principale de lapplication <b>Papillon</b>
*/
public FenetreAjout(Main parent) {
super("Ajouter un rappel");
ImageIcon logo = new ImageIcon("logo.png");
setIconImage(logo.getImage());
setSize(350, 250);
setAlwaysOnTop(true);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Layout principal
setLayout(new BorderLayout(10, 10));
JPanel centre = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(4, 4, 4, 4);
c.fill = GridBagConstraints.HORIZONTAL;
add(centre, BorderLayout.CENTER);
// Titre
JLabel lblTitre = new JLabel("Titre :");
champTitre = new JTextField(50);
champTitre.setDocument(new LimiteContenu(50));
c.gridx = 0;
c.gridy = 1;
c.weightx = 0;
centre.add(lblTitre, c);
c.gridx = 1;
c.gridy = 1;
c.weightx = 1;
centre.add(champTitre, c);
// Contenu
JLabel lblContenu = new JLabel("Contenu :");
champContenu = new JTextArea(4, 20);
champContenu.setDocument(new LimiteContenu(200));
champContenu.setLineWrap(true); // active le retour à la ligne
champContenu.setWrapStyleWord(true); // évite de couper un mot en plein milieu
JScrollPane scroll = new JScrollPane(champContenu,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
c.gridx = 0;
c.gridy = 2;
c.weightx = 0;
c.fill = GridBagConstraints.BOTH;
centre.add(lblContenu, c);
c.gridx = 1;
c.gridy = 2;
c.weightx = 1.0;
c.weighty = 1.0;
centre.add(scroll, c);
// Rang
JLabel lblrang = new JLabel("Rang :");
c.gridx = 0;
c.gridy = 3;
c.weightx = 0;
c.weighty = 0.0;
centre.add(lblrang, c);
c.gridx = 1;
c.gridy = 3;
c.weightx = 1;
centre.add(rang, c);
// Theme
c.gridx = 0;
c.gridy = 4;
c.weightx = 0;
centre.add(new JLabel("Theme :"), c);
// liste déroulante de couleurs
c.gridx = 1;
c.gridy = 4;
c.weightx = 1;
comboTheme.setRenderer(new CouleurList());
comboTheme.setSelectedItem("Bleu"); // valeur par défaut
centre.add(comboTheme, c);
// Bas : boutons
JPanel bas = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 10));
listBtnAjout = new GestionAjout(this,parent,champTitre,champContenu,rang,comboTheme);
bas.add(listBtnAjout.get(0));
bas.add(listBtnAjout.get(1));
add(bas, BorderLayout.SOUTH);
}
}

View File

@@ -0,0 +1,141 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
/**
* La classe <code>FenetreModif</code> permet dafficher une fenêtre
* dédiée à la modification dun rappel existant dans lapplication <b>Papillon</b>.
* <p>
* Elle reprend les informations du rappel sélectionné et permet à lutilisateur
* de les modifier avant de valider les changements.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class FenetreModif extends JFrame {
/** Gestionnaire des boutons de modification. */
private GestionModif listBtnModif;
/** Champ de saisie pour le titre du rappel. */
private final JTextField champTitre;
/** Champ de saisie pour le contenu du rappel. */
private final JTextArea champContenu;
/** Liste de niveaux de priorité disponibles. */
private Integer[] nombres = {1, 2, 3, 4, 5};
/** Sélecteur du niveau de priorité. */
private JComboBox<Integer> rang = new JComboBox<>(nombres);
/** Liste des noms de thèmes disponibles. */
private final String[] nomsCouleurs = {"Bleu", "Rouge", "Vert", "Jaune", "Rose"};
/** Sélecteur du thème du rappel. */
private final JComboBox<String> comboTheme = new JComboBox<>(nomsCouleurs);
/**
* Constructeur de la fenêtre de modification.
*
* @param parent la fenêtre principale de lapplication <b>Papillon</b>
* @param rappel le rappel à modifier
*/
public FenetreModif(Main parent, Rappel rappel) {
super("Modifier un rappel");
ImageIcon logo = new ImageIcon("logo.png");
setIconImage(logo.getImage());
setSize(350, 250);
setResizable(false);
setAlwaysOnTop(true);
setLocation(parent.getLocation()); // même position que Main
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Layout principal
setLayout(new BorderLayout(10, 10));
JPanel centre = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(4, 4, 4, 4);
c.fill = GridBagConstraints.HORIZONTAL;
add(centre, BorderLayout.CENTER);
// Titre
JLabel lblTitre = new JLabel("Titre :");
champTitre = new JTextField(20);
champTitre.setDocument(new LimiteContenu(50));
c.gridx = 0;
c.gridy = 1;
c.weightx = 0;
centre.add(lblTitre, c);
c.gridx = 1;
c.gridy = 1;
c.weightx = 1;
centre.add(champTitre, c);
// Contenu
JLabel lblContenu = new JLabel("Contenu :");
champContenu = new JTextArea(4, 20);
champContenu.setDocument(new LimiteContenu(200));
champContenu.setLineWrap(true); // active le retour à la ligne
champContenu.setWrapStyleWord(true); // évite de couper un mot en plein milieu
JScrollPane scroll = new JScrollPane(champContenu,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
c.gridx = 0;
c.gridy = 2;
c.weightx = 0;
c.fill = GridBagConstraints.BOTH;
centre.add(lblContenu, c);
c.gridx = 1;
c.gridy = 2;
c.weightx = 1.0;
c.weighty = 1.0;
centre.add(scroll, c);
// rang
rang.setSelectedIndex(rappel.getRang()-1);
JLabel lblRang = new JLabel("Rang :");
c.gridx = 0;
c.gridy = 3;
c.weightx = 0;
c.weighty = 0.0;
centre.add(lblRang, c);
c.gridx = 1;
c.gridy = 3;
c.weightx = 1;
centre.add(rang, c);
// theme
c.gridx = 0;
c.gridy = 4;
c.weightx = 0;
centre.add(new JLabel("Theme :"), c);
// liste déroulante de couleurs
c.gridx = 1;
c.gridy = 4;
c.weightx = 1;
comboTheme.setRenderer(new CouleurList());
comboTheme.setSelectedItem(rappel.getTheme()); // valeur par défaut
centre.add(comboTheme, c);
// add(centre, BorderLayout.CENTER);
// Bas : boutons
JPanel bas = new JPanel(new FlowLayout(FlowLayout.RIGHT));
listBtnModif = new GestionModif(this,parent,champTitre,champContenu,rang,comboTheme,rappel);
bas.add(listBtnModif.get(0));
bas.add(listBtnModif.get(1));
add(bas, BorderLayout.SOUTH);
champTitre.setText(rappel.getTitre());
champContenu.setText(rappel.getContenu());
}
}

View File

@@ -0,0 +1,126 @@
package fr.iutfbleau.papillon;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
/**
* La classe <code>FenetreRappel</code> représente la fenêtre daffichage
* détaillée dun rappel dans lapplication <b>Papillon</b>.
* <p>
* Elle affiche les informations complètes du rappel sélectionné
* (titre, contenu, thème, et priorité) et permet à lutilisateur
* de le modifier ou de fermer la fenêtre.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class FenetreRappel extends JFrame implements ActionListener{
/** Bouton permettant de fermer la fenêtre. */
private final JButton btnFermer = new JButton("Fermer");
/** Bouton permettant douvrir la fenêtre de modification du rappel. */
private final JButton btnModifier = new JButton("Modifier");
/** Référence vers la fenêtre principale de lapplication. */
private final Main main;
/** Référence vers le rappel à afficher. */
private Rappel rappel;
/**
* Constructeur de la fenêtre daffichage dun rappel.
*
* @param r le rappel à afficher
* @param main la fenêtre principale
*/
public FenetreRappel(Rappel r, Main main) {
super("Rappel : " + r.getTitre());
ImageIcon logo = new ImageIcon("logo.png");
setIconImage(logo.getImage());
this.main = main;
this.rappel = r;
setSize(350, 250);
setLocationRelativeTo(null);
setResizable(false);
setAlwaysOnTop(true);
setLocation(main.getLocation());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
JLabel titre = new JLabel("<html><h2>" + r.getTitre() + "</h2></html>");
JTextArea contenu = new JTextArea(r.getContenu());
contenu.setLineWrap(true);
contenu.setWrapStyleWord(true);
contenu.setEditable(false);
JLabel infos = new JLabel("<html><i>Thème : " + r.getTheme() + " <br>Rang : " + r.getRang() + "</i></html>");
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(4, 4, 4, 4);
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(titre, c);
c.gridy = 1;
c.weightx = 1.0;
c.weighty = 1.0;
c.gridwidth = 2;
c.fill = GridBagConstraints.BOTH;
panel.add(new JScrollPane(contenu), c);
c.gridx = 0;
c.gridy = 2;
c.weightx = 0;
c.weighty = 0;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.WEST;
panel.add(infos, c);
btnModifier.addActionListener(this);
btnFermer.addActionListener(this);
JPanel btnPanel = new JPanel();
c.gridx = 1;
c.gridy = 2;
c.weightx = 0;
c.weighty = 0;
c.anchor = GridBagConstraints.EAST;
btnPanel.add(btnModifier);
btnPanel.add(btnFermer);
panel.add(btnPanel, c);
setContentPane(panel);
setVisible(true);
main.dispose();
}
/**
* Gère les actions effectuées sur les boutons de la fenêtre.
* <ul>
* <li><b>Fermer</b> : ferme la fenêtre actuelle.</li>
* <li><b>Modifier</b> : ouvre la fenêtre de modification du rappel.</li>
* </ul>
*
* @param e lévénement daction déclenché
*/
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnFermer) {
Main reParent = new Main();
reParent.setLocation(this.getLocation());
reParent.setVisible(true);
this.dispose();
}
else if (e.getSource() == btnModifier) {
FenetreModif f = new FenetreModif(main,rappel);
f.setVisible(true);
this.dispose();
}
}
}

View File

@@ -0,0 +1,127 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
/**
* La classe <code>GestionAjout</code> gère les boutons de la fenêtre
* dajout dun rappel dans lapplication <b>Papillon</b>.
* <p>
* Elle contient les boutons <b>Valider</b> et <b>Annuler</b>, et définit
* le comportement associé à chacun deux.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class GestionAjout extends ArrayList<JButton> implements ActionListener{
/** Bouton de validation. */
private final JButton boutonValider;
/** Bouton d'annulation. */
private final JButton boutonAnnuler;
/** Champ de saisie pour le titre du rappel. */
private final JTextField champTitre;
/** Champ de saisie pour le contenu du rappel. */
private final JTextArea champContenu;
/** Sélecteur du niveau de priorité. */
private JComboBox<Integer> rang;
/** Sélecteur du thème du rappel. */
private final JComboBox<String> comboTheme;
/** Référence à la fenêtre principale. */
private final Main parent;
/** Référence à la fenêtre d'ajout. */
private final JFrame f;
/**
* Constructeur du gestionnaire de boutons pour la fenêtre dajout.
*
* @param f la fenêtre dajout
* @param parent la fenêtre principale
* @param champTitre le champ de texte pour le titre
* @param champContenu la zone de texte pour le contenu
* @param rang la liste déroulante de priorité
* @param comboTheme la liste déroulante du thème
*/
public GestionAjout(JFrame f, Main parent, JTextField champTitre, JTextArea champContenu, JComboBox<Integer> rang, JComboBox<String> comboTheme){
this.f = f;
this.parent = parent;
this.champTitre = champTitre;
this.champContenu = champContenu;
this.rang = rang;
this.comboTheme = comboTheme;
boutonValider = new JButton("Valider");
boutonAnnuler = new JButton("Annuler");
this.add(boutonValider);
this.add(boutonAnnuler);
boutonValider.addActionListener(this);
boutonAnnuler.addActionListener(this);
}
/**
* Gère les actions effectuées sur les boutons de la fenêtre.
* <p>
* Si lutilisateur clique sur <b>Annuler</b>, la fenêtre dajout est fermée
* et la fenêtre principale est réaffichée.
* Si lutilisateur clique sur <b>Valider</b>, un nouveau rappel est créé
* et ajouté à la liste principale.
* </p>
*
* @param e lévénement daction déclenché par un clic sur un bouton
*/
@Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == boutonAnnuler) {
// revenir à la fenêtre principale
Point pos = f.getLocation();
parent.setLocation(pos);
parent.setVisible(true);
f.dispose();
return;
}
if (src == boutonValider) {
String titre = champTitre.getText().trim();
String contenu = champContenu.getText().trim();
int Nrang = (Integer) rang.getSelectedItem();
String cTheme = (String)comboTheme.getSelectedItem();
GestionRappel g = new GestionRappel();
if (titre.isEmpty()) {
JOptionPane.showMessageDialog(f, "Veuillez remplir tout le titre.", "Champs manquants", JOptionPane.WARNING_MESSAGE);
return;
}else{
try{
g.ajouter(titre, contenu, cTheme, Nrang);
} catch (Exception ex) {
ex.printStackTrace(); // affiche l'erreur dans le terminal
}
}
Main reParent = new Main();
reParent.setLocation(f.getLocation());
reParent.setVisible(true);
f.dispose();
}
}
}

View File

@@ -0,0 +1,133 @@
package fr.iutfbleau.papillon;
import java.util.ArrayList;
import javax.swing.*;
import java.awt.event.*;
/**
* La classe <code>GestionModif</code> gère les boutons de la fenêtre
* de modification dun rappel dans lapplication <b>Papillon</b>.
* <p>
* Elle permet à lutilisateur de valider ou dannuler les changements
* effectués sur un rappel existant.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class GestionModif extends ArrayList<JButton> implements ActionListener{
/** Bouton de validation. */
private final JButton boutonValider;
/** Bouton d'annulation. */
private final JButton boutonAnnuler;
/** Champ de saisie pour le titre du rappel. */
private final JTextField champTitre;
/** Champ de saisie pour le contenu du rappel. */
private final JTextArea champContenu;
/** Sélecteur du niveau de priorité. */
private JComboBox<Integer> rang;
/** Sélecteur du thème du rappel. */
private final JComboBox<String> comboTheme;
/** Référence au rappel à modifier. */
private Rappel rappel;
/** Gestionnaire des commandes agissant sur les rappels. */
private final GestionRappel ges = new GestionRappel();
/** Référence à la fenêtre principale. */
private final Main parent;
/** Référence à la fenêtre de modification. */
private final JFrame f;
/**
* Constructeur du gestionnaire de boutons pour la fenêtre de modification.
*
* @param f la fenêtre de modification
* @param parent la fenêtre principale
* @param champTitre le champ de texte pour le titre
* @param champContenu la zone de texte pour le contenu
* @param rang la liste déroulante de priorité
* @param comboTheme la liste déroulante du thème
* @param r le rappel à modifier
*/
public GestionModif(JFrame f, Main parent, JTextField champTitre, JTextArea champContenu, JComboBox<Integer> rang, JComboBox<String> comboTheme, Rappel r){
this.f = f;
this.parent = parent;
this.champTitre = champTitre;
this.champContenu = champContenu;
this.rang = rang;
this.comboTheme = comboTheme;
this.rappel = r;
boutonValider = new JButton("Valider");
boutonAnnuler = new JButton("Annuler");
this.add(boutonValider);
this.add(boutonAnnuler);
boutonValider.addActionListener(this);
boutonAnnuler.addActionListener(this);
}
/**
* Gère les actions effectuées sur les boutons de la fenêtre.
* <p>
* Si lutilisateur clique sur <b>Annuler</b>, la fenêtre principale est réaffichée.
* Si lutilisateur clique sur <b>Valider</b>, les changements sont enregistrés.
* </p>
*
* @param e lévénement daction déclenché par un bouton
*/
@Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == boutonAnnuler) {
parent.setLocation(f.getLocation());
parent.setVisible(true);
f.dispose();
return;
}
if (src == boutonValider) {
String t = champTitre.getText().trim();
String c = champContenu.getText().trim();
int r = (Integer) rang.getSelectedItem();
String th = (String) comboTheme.getSelectedItem();
if (t.isEmpty()) {
JOptionPane.showMessageDialog(f, "Veuillez remplir le titre.", "Champs manquants", JOptionPane.WARNING_MESSAGE);
return;
}
// MAJ directe du rappel
rappel.setTitre(t);
rappel.setContenu(c);
rappel.setRang(r);
rappel.setTheme(th);
try{
ges.modifierParId(rappel.getId(), rappel);
} catch (Exception ex) {
ex.printStackTrace();
}
Main reParent = new Main();
reParent.setLocation(f.getLocation());
reParent.setVisible(true);
f.dispose();
}
}
}

View File

@@ -0,0 +1,110 @@
package fr.iutfbleau.papillon;
import java.sql.SQLException;
import java.util.List;
/**
* La classe <code>GestionRappel</code> gère les opérations CRUD
* (création, lecture, modification, suppression) sur les rappels
* associés à lutilisateur courant.
* <p>
* Elle sappuie sur les classes <code>Rappel</code>, <code>RappelBD</code>,
* <code>UserKey</code> et <code>UtilisateurBD</code> pour interagir
* avec la base de données.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class GestionRappel {
/** Identifiant de l'utilisateur courant. */
private final int utilisateurId;
/**
* Constructeur de la classe <code>GestionRappel</code>.
* <p>
* Initialise lidentifiant utilisateur en se basant sur la clé locale.
* Si aucun utilisateur nexiste encore, il est automatiquement créé
* dans la base de données.
* </p>
*/
public GestionRappel() {
int uid = -1;
try {
String cle = UserKey.lireOuCreerCle(); // clé locale
uid = UtilisateurBD.getOrCreateIdByKey(cle); // crée ou récupère utilisateur
} catch (Exception e) {
e.printStackTrace();
}
this.utilisateurId = uid;
System.out.println("Utilisateur courant id=" + this.utilisateurId);
}
/**
* Ajoute un nouveau rappel pour lutilisateur courant.
*
* @param titre le titre du rappel
* @param contenu le contenu textuel du rappel
* @param theme le thème associé au rappel
* @param rang la priorité du rappel
* @return le nombre de lignes affectées ou lID du rappel ajouté
* @throws SQLException si une erreur survient lors de lajout
*/
public int ajouter(String titre, String contenu, String theme, int rang) throws SQLException {
Rappel r = new Rappel(titre, contenu, theme, rang);
return RappelBD.ajouter(r, this.utilisateurId);
}
/**
* Liste tous les rappels appartenant à lutilisateur courant.
*
* @return la liste des rappels de lutilisateur
* @throws SQLException si une erreur de communication avec la base survient
*/
public List<Rappel> lister() throws SQLException {
return RappelBD.listerParUtilisateur(this.utilisateurId);
}
/**
* Modifie un rappel existant à partir de son identifiant.
*
* @param id lidentifiant du rappel à modifier
* @param r lobjet <code>Rappel</code> contenant les nouvelles valeurs
* @return le nombre de lignes modifiées
* @throws SQLException si une erreur survient lors de la mise à jour
*/
public int modifierParId(int id, Rappel r) throws SQLException {
return RappelBD.modifier(id, r, this.utilisateurId);
}
/**
* Supprime un rappel de la base de données selon son identifiant.
*
* @param id lidentifiant du rappel à supprimer
* @return le nombre de lignes supprimées
* @throws SQLException si une erreur survient lors de la suppression
*/
public int supprimerParId(int id) throws SQLException {
return RappelBD.supprimer(id, this.utilisateurId);
}
/**
* Supprime tous les rappels appartenant à lutilisateur courant.
*
* @return le nombre de rappels supprimés
* @throws SQLException si une erreur survient lors de la suppression
*/
public int viderTousMesRappels() throws SQLException {
return RappelBD.supprimerToutPourUtilisateur(this.utilisateurId);
}
/**
* Renvoie lidentifiant de lutilisateur courant.
*
* @return lID utilisateur
*/
public int getUtilisateurId() {
return this.utilisateurId;
}
}

View File

@@ -0,0 +1,48 @@
package fr.iutfbleau.papillon;
import javax.swing.text.*;
/**
* La classe <code>LimiteContenu</code> permet de limiter le nombre
* de caractères pouvant être saisis dans un champ de texte Swing.
* <p>
* Elle hérite de <code>PlainDocument</code> et empêche toute insertion
* dépassant la limite définie.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class LimiteContenu extends PlainDocument {
/** Limite de caractères autorisés. */
private int limite;
/**
* Constructeur qui définit la limite de caractères.
*
* @param limite le nombre maximum de caractères autorisés
*/
public LimiteContenu(int limite) {
this.limite = limite;
}
/**
* Insère une chaîne dans le document si elle ne dépasse pas la limite autorisée.
*
* @param offset la position dinsertion
* @param str la chaîne à insérer
* @param attr les attributs du texte
* @throws BadLocationException si la position est invalide
*/
@Override
public void insertString(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null){
return;
}
if ((getLength() + str.length()) <= limite) {
super.insertString(offset, str, attr);
}
}
}

View File

@@ -0,0 +1,203 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
/**
* La classe <code>Main</code> représente la fenêtre principale
* de lapplication <b>Papillon</b>.
* <p>
* Elle gère laffichage des rappels, leur tri, ainsi que les
* interactions avec les boutons dajout, de suppression et de modification.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class Main extends JFrame implements ActionListener{
/** Liste des panneaux représentant les rappels. */
private List<PanelRappel> listRpl = new ArrayList<>();
/** Panneau contenant la liste des rappels. */
private JPanel liste = new JPanel();
/** Menu déroulant permettant de trier les rappels par priorité. */
private ChoixRang trier = new ChoixRang();
/** Conteneur racine de la fenêtre principale. */
private JPanel root = new JPanel(new BorderLayout());
/**
* Constructeur de la fenêtre principale de lapplication.
* <p>
* Initialise les composants graphiques, configure la disposition et
* charge la liste des rappels au démarrage.
* </p>
*/
public Main(){
super("Papillon");
ImageIcon logo = new ImageIcon("logo.png");
setIconImage(logo.getImage());
trier = new ChoixRang();
trier.addActionListener(this);
// Taille fixe
setSize(350, 250);
setResizable(false);
setAlwaysOnTop(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Titre en haut
JLabel titre = new JLabel("Rappel : Papillon", SwingConstants.CENTER);
titre.setBorder(BorderFactory.createEmptyBorder(6,10,6,10));
// titre.setBackground(Color.CYAN);
// ----- Grille centrale -----
JPanel body = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
Crud crud = new Crud(this);
// Colonne 0 : boutons
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(4, 4, 4, 4);
for(int i = 0; i< crud.size() ;i++){
c.gridx = i;
c.gridy = 4;
c.weighty = 0;
c.weightx = 1;
body.add(crud.get(i), c);
}
// Colonne 1 : liste verticale de Rappel dans un JScrollPane
liste = new JPanel();
//Rappels
this.setTrie(trier.getSelectedIndex());
liste=this.getRPanel();
liste.setLayout(new BoxLayout(liste, BoxLayout.Y_AXIS));
JScrollPane scroll = new JScrollPane(
liste,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
scroll.getVerticalScrollBar().setUnitIncrement(16); // molette fluide
// place le scrollpane a droite, sur la hauteur des 2 lignes
c.gridx = 0; c.gridy = 1; c.gridwidth = 3;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(0, 0, 0, 0);
c.weightx = 1.0; // prend la largeur dispo
c.weighty = 1.0; // prend la hauteur dispo
body.add(scroll, c);
c.gridx=0; c.gridy=0;
c.weightx = 0.0; c.weighty = 0.0;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.SOUTHEAST;
c.insets = new Insets(1, 1, 1, 1);
body.add(trier,c);
// Conteneur racine
root.add(titre, BorderLayout.NORTH);
root.add(body, BorderLayout.CENTER);
setContentPane(root);
}
/**
* Renvoie la liste des panneaux de rappels actuellement affichés.
*
* @return une liste de <code>PanelRappel</code>
*/
public List<PanelRappel> getPanelRpl(){
return listRpl;
}
/**
* Met à jour la fenêtre principale après une modification
* (ajout, suppression ou édition dun rappel).
* <p>
* Cette méthode recharge le panneau des rappels
* et force le recalcul de laffichage.
* </p>
*/
public void maj(){
liste = this.getRPanel();
liste.revalidate(); // recalcul du layout
liste.repaint();
this.revalidate();
this.repaint();
}
/**
* Applique un tri des rappels selon leur rang de priorité.
*
* @param rang le niveau de priorité sélectionné dans le menu
*/
public void setTrie(int rang){
listRpl = new ArrayList<>();
GestionRappel g = new GestionRappel();
List<Rappel> listBd = new ArrayList<>();
try {
listBd = g.lister();
} catch (Exception ex) {
ex.printStackTrace();
}
if(rang>0){
for(int i=0;i<listBd.size();i++){
PanelRappel rappel = new PanelRappel(listBd.get(i), this);
if(listBd.get(i).getRang()==rang){
liste.add(rappel);
listRpl.add(rappel);
}
}
}else{
for (int i = 0; i < listBd.size() ; i++) {
PanelRappel r = new PanelRappel(listBd.get(i), this);
liste.add(r);
listRpl.add(r);
}
}
}
/**
* Renvoie le panneau contenant les rappels.
*
* @return le panneau de type <code>JPanel</code> affichant les rappels
*/
public JPanel getRPanel(){
return liste;
}
/**
* Gère les actions utilisateur sur le menu déroulant de tri.
* <p>
* Réinitialise la liste et applique le tri sélectionné.
* </p>
*
* @param ea lévénement daction déclenché
*/
@Override
public void actionPerformed(ActionEvent ea) {
liste.removeAll();
trier.tirage(this);
}
}

View File

@@ -0,0 +1,255 @@
package fr.iutfbleau.papillon;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* La classe <code>PanelRappel</code> représente laffichage graphique
* dun rappel dans lapplication <b>Papillon</b>.
* <p>
* Chaque panneau contient le titre, un aperçu du contenu, ainsi quune
* couleur correspondant au thème du rappel.
* Lutilisateur peut interagir avec ce panneau (sélection, clic droit, etc.).
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class PanelRappel extends JPanel implements ActionListener, MouseListener {
/** Indique si le rappel est actuellement sélectionné. */
private boolean estSelectionne = false;
/** Label affichant le titre du rappel. */
private JLabel lbtitre;
/** Label affichant un aperçu du contenu du rappel. */
private JLabel lbcontenu;
/** Référence vers le rappel associé à ce panneau. */
private Rappel r;
/** Menu contextuel (clic droit). */
private JPopupMenu menu;
/** Élément du menu permettant douvrir le rappel. */
private JMenuItem itemOuvrir;
/** Référence à la fenêtre principale. */
private Main main;
/** Liste des couleurs disponibles pour les thèmes. */
private static CouleurList couleur = new CouleurList();
/**
* Constructeur du panneau associé à un rappel et à la fenêtre principale.
*
* @param r le rappel à afficher
* @param main la fenêtre principale
*/
public PanelRappel(Rappel r, Main main) {
super(new BorderLayout(2, 0));
this.main = main;
createPanel(r);
}
/**
* Constructeur du panneau associé à un rappel sans référence à la fenêtre principale.
*
* @param r le rappel à afficher
*/
public PanelRappel(Rappel r) {
super(new BorderLayout(2, 0));
createPanel(r);
}
/**
* Initialise et configure le panneau pour afficher les informations du rappel.
*
* @param r le rappel à afficher
*/
public void createPanel(Rappel r){
this.r = r;
// Titre et contenu raccourci
lbtitre = new JLabel("[" + r.getRang() + "] " + r.getTitre());
lbcontenu = new JLabel(
"<html>" + (r.getContenu().length() > 40 ? r.getContenu().substring(0, 40) + "..." : r.getContenu()) + "</html>"
);
// - Apparence de base
this.setPreferredSize(new Dimension(70, 50));
this.setBackground(couleur.couleurDe(r.getTheme()));
this.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 2));
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
// - Position du titre
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.fill = GridBagConstraints.NONE;
add(lbtitre, c);
// -Position du contenu
c.gridx = 0;
c.gridy = 1;
c.weightx = 1;
c.fill = GridBagConstraints.NONE;
add(lbcontenu, c);
// - Menu contextuel (clic droit)
menu = new JPopupMenu();
itemOuvrir = new JMenuItem("Ouvrir");
itemOuvrir.addActionListener(this);
menu.add(itemOuvrir);
// - Activation des clics
addMouseListener(this);
}
// GETTERS
/**
* Indique si le panneau est actuellement sélectionné.
*
* @return true si le panneau est sélectionné, false sinon
*/
public boolean getSelection() {
return estSelectionne;
}
/**
* Renvoie lidentifiant du rappel affiché.
*
* @return lidentifiant unique du rappel
*/
public int getId() {
return r.getId();
}
/**
* Renvoie le rappel associé à ce panneau.
*
* @return le rappel affiché dans ce panneau
*/
public Rappel getRappel() {
return r;
}
/**
* Gère les actions déclenchées par les éléments du menu contextuel.
* <p>
* Si lutilisateur clique sur "Ouvrir", la fenêtre détaillée du rappel est affichée.
* </p>
*
* @param e lévénement daction déclenché
*/
@Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == itemOuvrir) {
// ouverture complète depuis le menu clic droit
new FenetreRappel(r, main);
}
}
/**
* Gère les clics de souris sur le panneau.
* <p>
* Un clic gauche sélectionne/désélectionne le panneau,
* tandis quun clic droit affiche le menu contextuel.
* </p>
*
* @param e lévénement de souris détecté
*/
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
menu.show(e.getComponent(), e.getX(), e.getY());
} else {
// clic gauche = sélection / désélection
estSelectionne = !estSelectionne;
majApparence();
}
}
/**
* Gère la libération du clic de souris.
* <p>
* Si le clic est un clic droit, le menu contextuel saffiche.
* </p>
*
* @param e lévénement de souris
*/
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
/**
* Gère les clics simples ou doubles sur le panneau.
* <p>
* Un double clic gauche ouvre la fenêtre de rappel complète.
* </p>
*
* @param e lévénement de souris
*/
@Override
public void mouseClicked(MouseEvent e) {
// === Double clic pour ouvrir la vue complète ===
if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
new FenetreRappel(r, main);
}
}
/**
* Change lapparence du panneau lorsque la souris entre dans sa zone.
*
* @param e lévénement de souris
*/
@Override
public void mouseEntered(MouseEvent e) {
setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
}
/**
* Restaure la bordure du panneau lorsque la souris quitte sa zone.
*
* @param e lévénement de souris
*/
@Override
public void mouseExited(MouseEvent e) {
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
}
/**
* Met à jour lapparence du panneau en fonction de son état de sélection.
* <p>
* Si le panneau est sélectionné, son fond devient gris clair
* et une bordure noire est appliquée.
* Sinon, la couleur de fond correspond au thème du rappel.
* </p>
*/
private void majApparence() {
if (estSelectionne) {
setBackground(Color.LIGHT_GRAY);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
} else {
setBackground(couleur.couleurDe(r.getTheme()));
}
}
}

View File

@@ -0,0 +1,79 @@
package fr.iutfbleau.papillon;
/**
* La classe <code>Rappel</code> représente un rappel utilisateur,
* avec un titre, un contenu, un thème et un rang de priorité.
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class Rappel {
private int id;
private String titre;
private String contenu;
private String theme;
private int rang;
/** Constructeur vide (utilisé notamment pour la lecture SQL). */
public Rappel() {}
/**
* Constructeur dun nouveau rappel sans identifiant.
*
* @param titre le titre du rappel
* @param contenu le contenu ou la description
* @param theme la catégorie ou le thème du rappel
* @param rang la priorité ou lordre daffichage
*/
public Rappel(String titre, String contenu, String theme, int rang) {
this(0, titre, contenu, theme, rang);
}
/**
* Constructeur complet avec identifiant.
*
* @param id lidentifiant du rappel
* @param titre le titre du rappel
* @param contenu le contenu
* @param theme le thème
* @param rang le rang de priorité
*/
public Rappel(int id, String titre, String contenu, String theme, int rang) {
this.id = id;
this.titre = titre;
this.contenu = contenu;
this.theme = theme;
this.rang = rang;
}
/** @return lidentifiant du rappel */
public int getId() { return id; }
/** @param id définit lidentifiant du rappel */
public void setId(int id) { this.id = id; }
/** @return le titre du rappel */
public String getTitre() { return titre; }
/** @param titre définit le titre du rappel */
public void setTitre(String titre) { this.titre = titre; }
/** @return le contenu du rappel */
public String getContenu() { return contenu; }
/** @param contenu définit le contenu du rappel */
public void setContenu(String contenu) { this.contenu = contenu; }
/** @return le thème du rappel */
public String getTheme() { return theme; }
/** @param theme définit le thème du rappel */
public void setTheme(String theme) { this.theme = theme; }
/** @return le rang de priorité du rappel */
public int getRang() { return rang; }
/** @param rang définit le rang de priorité du rappel */
public void setRang(int rang) { this.rang = rang; }
}

View File

@@ -0,0 +1,156 @@
package fr.iutfbleau.papillon;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* La classe <code>RappelBD</code> gère les interactions entre le programme
* et la table <b>rappel</b> dans la base de données.
* <p>
* Elle permet d'ajouter, de modifier, de supprimer et de lister les rappels
* associés à un utilisateur spécifique à travers son identifiant (<code>utilisateur_id</code>).
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class RappelBD {
/**
* Ajoute un nouveau rappel dans la base de données pour un utilisateur donné.
*
* @param r l'objet {@link Rappel} à insérer dans la base
* @param utilisateurId l'identifiant de l'utilisateur propriétaire du rappel
* @return l'identifiant du rappel nouvellement inséré, ou -1 en cas d'erreur
* @throws SQLException si une erreur survient lors de la communication avec la base
*/
protected static int ajouter(Rappel r, int utilisateurId) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
String sql = "INSERT INTO rappel (utilisateur_id, titre, contenu, theme, rang) VALUES (?, ?, ?, ?, ?)";
PreparedStatement pst = cnx.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pst.setInt(1, utilisateurId);
pst.setString(2, r.getTitre());
pst.setString(3, r.getContenu());
pst.setString(4, r.getTheme());
pst.setInt(5, r.getRang());
pst.executeUpdate();
ResultSet rs = pst.getGeneratedKeys();
int id = -1;
if (rs.next()) {
id = rs.getInt(1);
}
rs.close();
pst.close();
cnx.close();
return id;
}
/**
* Récupère la liste complète des rappels appartenant à un utilisateur.
*
* @param utilisateurId l'identifiant de l'utilisateur
* @return une liste d'objets {@link Rappel} appartenant à cet utilisateur
* @throws SQLException si une erreur SQL survient lors de l'exécution
*/
protected static List<Rappel> listerParUtilisateur(int utilisateurId) throws SQLException {
String sql = "SELECT id, titre, contenu, theme, rang FROM rappel WHERE utilisateur_id = ? ORDER BY rang ASC, id ASC";
List<Rappel> res = new ArrayList<>();
Connection cnx = BaseDeDonnees.getConnexion();
PreparedStatement pst = cnx.prepareStatement(sql);
pst.setInt(1, utilisateurId);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
Rappel r = new Rappel(
rs.getInt("id"),
rs.getString("titre"),
rs.getString("contenu"),
rs.getString("theme"),
rs.getInt("rang")
);
res.add(r);
}
rs.close();
pst.close();
cnx.close();
return res;
}
/**
* Modifie un rappel existant dans la base de données.
*
* @param id l'identifiant du rappel à modifier
* @param r l'objet {@link Rappel} contenant les nouvelles données
* @param utilisateurId l'identifiant de l'utilisateur propriétaire du rappel
* @return le nombre de lignes modifiées (0 si aucun rappel n'a été trouvé)
* @throws SQLException si une erreur SQL survient
*/
protected static int modifier(int id, Rappel r, int utilisateurId) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
String sql = "UPDATE rappel SET titre = ?, contenu = ?, theme = ?, rang = ? WHERE id = ? AND utilisateur_id = ?";
PreparedStatement pst = cnx.prepareStatement(sql);
pst.setString(1, r.getTitre());
pst.setString(2, r.getContenu());
pst.setString(3, r.getTheme());
pst.setInt(4, r.getRang());
pst.setInt(5, id);
pst.setInt(6, utilisateurId);
int res = pst.executeUpdate();
pst.close();
cnx.close();
return res;
}
/**
* Supprime un rappel spécifique appartenant à un utilisateur.
*
* @param id l'identifiant du rappel à supprimer
* @param utilisateurId l'identifiant de l'utilisateur propriétaire
* @return le nombre de lignes supprimées (0 si aucun rappel correspondant)
* @throws SQLException si une erreur SQL survient
*/
protected static int supprimer(int id, int utilisateurId) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
String sql = "DELETE FROM rappel WHERE id = ? AND utilisateur_id = ?";
PreparedStatement pst = cnx.prepareStatement(sql);
pst.setInt(1, id);
pst.setInt(2, utilisateurId);
int res = pst.executeUpdate();
pst.close();
cnx.close();
return res;
}
/**
* Supprime tous les rappels appartenant à un utilisateur spécifique.
*
* @param utilisateurId l'identifiant de l'utilisateur dont les rappels doivent être supprimés
* @return le nombre total de lignes supprimées
* @throws SQLException si une erreur SQL survient
*/
protected static int supprimerToutPourUtilisateur(int utilisateurId) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
String sql = "DELETE FROM rappel WHERE utilisateur_id = ?";
PreparedStatement pst = cnx.prepareStatement(sql);
pst.setInt(1, utilisateurId);
int lignes = pst.executeUpdate();
pst.close();
cnx.close();
return lignes;
}
}

View File

@@ -0,0 +1,29 @@
package fr.iutfbleau.papillon;
/**
* La classe <code>Start</code> constitue le point dentrée principal
* de lapplication <b>Papillon</b>.
* <p>
* Elle initialise la fenêtre principale et lance linterface graphique
* de lapplication.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class Start{
/**
* Méthode principale exécutée au démarrage du programme.
* <p>
* Crée une instance de la fenêtre principale (<code>Main</code>)
* et laffiche à lécran.
* </p>
*
* @param args les arguments passés en ligne de commande (non utilisés)
*/
public static void main(String[] args) {
Main f = new Main();
f.setVisible(true);
}
}

View File

@@ -0,0 +1,104 @@
package fr.iutfbleau.papillon;
import java.io.*;
import java.util.UUID;
/**
* La classe <code>UserKey</code> permet de gérer une clé d'identification locale
* unique pour un utilisateur du logiciel <b>Papillon</b>.
*
* <p>
* Cette clé est stockée dans un fichier caché nommé <code>.papillon_id</code>
* dans le répertoire personnel de l'utilisateur.
* Elle sert à identifier l'utilisateur sans avoir besoin de système de connexion
* ou d'authentification centralisée.
* </p>
*
* <p>
* Lors du premier lancement du programme, si le fichier nexiste pas ou est vide,
* une clé unique (UUID) est automatiquement générée, enregistrée dans ce fichier
* et réutilisée pour les prochaines exécutions.
* </p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class UserKey {
/**
* Lit la clé stockée dans le fichier <code>~/.papillon_id</code>
* ou en génère une nouvelle si le fichier n'existe pas ou est vide.
*
* <p>Cette méthode est utilisée par {@link GestionRappel} pour associer
* chaque utilisateur à ses données locales.</p>
*
* @return une chaîne de caractères représentant la clé unique de l'utilisateur
*/
protected static String lireOuCreerCle() {
// Récupère le dossier personnel de lutilisateur
String home = System.getProperty("user.home");
File fichier = new File(home, ".papillon_id");
String cle = "";
try {
// Si le fichier existe déjà on lit son contenu
if (fichier.exists()) {
if (fichier.length() == 0) {
cle = genererCle(); // Génère une clé unique
ecrireCle(fichier, cle);
System.out.println("Le fichier de clé est vide. Génération d'une nouvelle clé.");
}
FileReader fr = new FileReader(fichier);
BufferedReader br = new BufferedReader(fr);
cle = br.readLine(); // lit la première ligne (la clé)
br.close();
fr.close();
System.out.println("Clé existante trouvée : " + cle);
}
// Sinon, on génère une nouvelle clé et on lécrit dans le fichier
else {
cle = genererCle();
ecrireCle(fichier, cle);
System.out.println("Nouvelle clé générée et enregistrée : " + cle);
}
} catch (IOException e) {
System.err.println("Erreur lors de la lecture/écriture du fichier de clé : " + e.getMessage());
}
return cle;
}
/**
* Génère une nouvelle clé unique sous la forme d'un identifiant universel (UUID).
*
* <p>Cette méthode utilise la classe {@link java.util.UUID} pour générer
* une chaîne aléatoire unique et pratiquement impossible à deviner.</p>
*
* @return une chaîne aléatoire unique représentant une clé utilisateur
*/
private static String genererCle() {
return UUID.randomUUID().toString();
}
/**
* Écrit une clé donnée dans un fichier texte.
*
* <p>Cette méthode crée le fichier sil nexiste pas, puis enregistre
* la clé passée en paramètre sur la première ligne du fichier.</p>
*
* @param fichier le fichier dans lequel écrire la clé
* @param cle la clé à sauvegarder dans le fichier
* @throws IOException si une erreur survient lors de lécriture
*/
private static void ecrireCle(File fichier, String cle) throws IOException {
FileWriter fw = new FileWriter(fichier);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(cle);
bw.newLine();
bw.close();
fw.close();
}
}

View File

@@ -0,0 +1,52 @@
package fr.iutfbleau.papillon;
/**
* La classe <code>Utilisateur</code> représente un utilisateur unique
* du logiciel Papillon, identifié par une clé locale.
*
* @version 1.0
* @author Seri-khane Yolou, Aylane SEHL, Jenson VAL
*/
public class Utilisateur {
private int id;
private String cle;
/**
* Constructeur complet dun utilisateur.
*
* @param id lidentifiant de lutilisateur
* @param cle la clé unique didentification
*/
public Utilisateur(int id, String cle) {
this.id = id;
this.cle = cle;
}
/**
* Constructeur dun utilisateur à partir de sa clé uniquement.
*
* @param cle la clé unique didentification
*/
public Utilisateur(String cle) {
this.cle = cle;
}
/** @return lidentifiant de lutilisateur */
public int getId() { return id; }
/** @param id définit lidentifiant de lutilisateur */
public void setId(int id) { this.id = id; }
/** @return la clé unique de lutilisateur */
public String getCle() { return cle; }
/** @param cle définit la clé unique de lutilisateur */
public void setCle(String cle) { this.cle = cle; }
/** @return une représentation textuelle de lutilisateur */
@Override
public String toString() {
return "Utilisateur [id=" + id + ", cle=" + cle + "]";
}
}

View File

@@ -0,0 +1,84 @@
package fr.iutfbleau.papillon;
import java.sql.*;
/**
* La classe <code>UtilisateurBD</code> gère la table <b>utilisateur</b>
* de la base de données.
* <p>Elle permet de créer ou de récupérer un utilisateur à partir dune clé locale,
* et de lire un utilisateur complet via sa clé.</p>
*
* @version 1.0
* @author Seri-khane YOLOU, Aylane SEHL, Jenson VAL
*/
public class UtilisateurBD {
/** Identifiant interne de lutilisateur. */
private static int id;
/**
* Récupère ou crée un utilisateur en fonction de sa clé unique.
*
* @param cle la clé unique associée à lutilisateur
* @return lidentifiant de lutilisateur correspondant
* @throws SQLException si une erreur SQL survient
*/
public static int getOrCreateIdByKey(String cle) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
// Vérifie si un utilisateur existe déjà avec cette clé
String sqlSelect = "SELECT id FROM utilisateur WHERE cle = ?";
PreparedStatement pstSelect = cnx.prepareStatement(sqlSelect);
pstSelect.setString(1, cle);
ResultSet rs = pstSelect.executeQuery();
if (rs.next()) {
id = rs.getInt("id");
} else {
// Sinon on en crée un nouveau
String sqlInsert = "INSERT INTO utilisateur (cle) VALUES (?)";
PreparedStatement pstInsert = cnx.prepareStatement(sqlInsert, Statement.RETURN_GENERATED_KEYS);
pstInsert.setString(1, cle);
pstInsert.executeUpdate();
ResultSet keys = pstInsert.getGeneratedKeys();
if (keys.next()) {
id = keys.getInt(1);
}
keys.close();
pstInsert.close();
}
rs.close();
pstSelect.close();
cnx.close();
return id;
}
/**
* Récupère un utilisateur complet à partir de sa clé.
*
* @param cle la clé unique de lutilisateur
* @return un objet {@link Utilisateur} si trouvé, sinon <code>null</code>
* @throws SQLException si une erreur SQL survient
*/
public static Utilisateur findByKey(String cle) throws SQLException {
Connection cnx = BaseDeDonnees.getConnexion();
String sql = "SELECT id, cle FROM utilisateur WHERE cle = ?";
PreparedStatement pst = cnx.prepareStatement(sql);
pst.setString(1, cle);
ResultSet rs = pst.executeQuery();
Utilisateur u = null;
if (rs.next()) {
u = new Utilisateur(rs.getInt("id"), rs.getString("cle"));
}
rs.close();
pst.close();
cnx.close();
return u;
}
}