Amélioration du code et des menus
This commit is contained in:
@@ -7,17 +7,61 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Listener pour animer un bouton lorsqu'il est survolé par la souris.
|
||||
* Cette classe permet d'agrandir ou de réduire la taille de la police et de changer la couleur du bouton
|
||||
* lorsque la souris entre ou sort de la zone du bouton.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Moncef STITI, Lenny FOULOU
|
||||
*/
|
||||
public class ButtonHoverAnimationListener implements ActionListener {
|
||||
|
||||
private int step = 0;
|
||||
/*
|
||||
* Compteur d'étapes pour l'animation
|
||||
*/
|
||||
private int step;
|
||||
|
||||
/*
|
||||
* Incrément de mise à l'échelle à chaque étape
|
||||
*/
|
||||
private final float scaleIncrement;
|
||||
|
||||
/*
|
||||
* Indique si la souris entre ou quitte le bouton
|
||||
*/
|
||||
private final boolean entering;
|
||||
|
||||
/*
|
||||
* Référence au bouton à animer
|
||||
*/
|
||||
private final JButton button;
|
||||
|
||||
/*
|
||||
* Couleur d'origine du bouton
|
||||
*/
|
||||
private final Color originalColor;
|
||||
|
||||
/*
|
||||
* Police d'origine du bouton
|
||||
*/
|
||||
private final Font originalFont;
|
||||
|
||||
/*
|
||||
* Échelle actuelle de la police
|
||||
*/
|
||||
private float currentScale = 1.0f;
|
||||
|
||||
/**
|
||||
* Constructeur pour initialiser les variables du listener.
|
||||
*
|
||||
* @param entering Indique si la souris entre ou quitte le bouton
|
||||
* @param button Référence au bouton à animer
|
||||
* @param originalColor Couleur d'origine du bouton
|
||||
* @param originalFont Police d'origine du bouton
|
||||
*/
|
||||
public ButtonHoverAnimationListener(boolean entering, JButton button, Color originalColor, Font originalFont) {
|
||||
this.step = 0;
|
||||
this.entering = entering;
|
||||
this.button = button;
|
||||
this.originalColor = originalColor;
|
||||
@@ -25,18 +69,29 @@ public class ButtonHoverAnimationListener implements ActionListener {
|
||||
this.scaleIncrement = (Options.HOVER_FONT_SCALE - 1.0f) / Options.ANIMATION_STEPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode appelée à chaque étape de l'animation.
|
||||
* Modifie la taille de la police et la couleur du bouton en fonction de l'état de l'animation.
|
||||
*
|
||||
* @param e l'événement d'action qui est émis par le Timer
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// Calcul de la nouvelle échelle en fonction de l'état "entrant" ou "sortant"
|
||||
currentScale = entering ? (1.0f + step * scaleIncrement) : (Options.HOVER_FONT_SCALE - step * scaleIncrement);
|
||||
|
||||
// Modification de la couleur du bouton en fonction de l'état "entrant" ou "sortant"
|
||||
button.setForeground(entering ? Options.BUTTON_HOVER_COLOR : originalColor);
|
||||
// Application de la nouvelle taille de police au bouton
|
||||
button.setFont(originalFont.deriveFont(originalFont.getSize2D() * currentScale));
|
||||
|
||||
// Incrémente le compteur d'étapes
|
||||
step++;
|
||||
// Si le nombre d'étapes est atteint, arrête le Timer et réinitialise les éléments si la souris sort
|
||||
if (step >= Options.ANIMATION_STEPS) {
|
||||
((Timer) e.getSource()).stop();
|
||||
if (!entering) {
|
||||
button.setFont(originalFont); // Restore the original font
|
||||
button.setFont(originalFont); // Restauration de la police originale si la souris quitte le bouton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package fr.monkhanny.dorfromantik.game;
|
||||
|
||||
import fr.monkhanny.dorfromantik.enums.Biome;
|
||||
import fr.monkhanny.dorfromantik.enums.TileOrientation;
|
||||
import java.awt.Point;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@@ -57,14 +57,12 @@ public class ScoreManager {
|
||||
newPocket.addTile(tile);
|
||||
pockets.add(newPocket);
|
||||
biomeToPocketMap.put(biome, newPocket);
|
||||
System.out.println("New pocket created with biome: " + biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculer le score après avoir ajouté la tuile
|
||||
recalculateScore();
|
||||
System.out.println("Current Score: " + currentScore);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,46 +81,6 @@ public class ScoreManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds a pocket connected to the given tile with the specified biome.
|
||||
*
|
||||
* @param tile The tile to check connections for.
|
||||
* @param biome The biome to match.
|
||||
* @return The connected pocket, or null if none found.
|
||||
*/
|
||||
private Pocket findConnectedPocket(Tile tile, Biome biome) {
|
||||
for (Pocket pocket : pockets) {
|
||||
if (pocket.getBiome() == biome) {
|
||||
for (Tile pocketTile : pocket.getTiles()) {
|
||||
if (pocketTile.isAdjacentTo(tile) && sharesBiome(tile, pocketTile, biome)) {
|
||||
return pocket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two tiles share a biome on any of their sides.
|
||||
*
|
||||
* @param tile1 The first tile.
|
||||
* @param tile2 The second tile.
|
||||
* @param biome The biome to match.
|
||||
* @return True if the tiles share the given biome on a connecting side.
|
||||
*/
|
||||
private boolean sharesBiome(Tile tile1, Tile tile2, Biome biome) {
|
||||
for (TileOrientation orientation : TileOrientation.values()) {
|
||||
if (tile1.getBiome(orientation) == biome && tile2.getBiome(orientation.oppositeOrientation()) == biome) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the score based on the current pockets.
|
||||
*/
|
||||
|
@@ -33,6 +33,7 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
private JSpinner startDateSpinner;
|
||||
private JSpinner endDateSpinner;
|
||||
private ActionListener buttonListener;
|
||||
private JCheckBox developerSeriesCheckBox;
|
||||
|
||||
public GameModeSelectionPanel(ActionListener buttonListener, JFrame gameModeFrame, MainMenu mainMenu) {
|
||||
this.buttonListener = buttonListener;
|
||||
@@ -62,7 +63,7 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
background.add(mainPanel, BorderLayout.CENTER);
|
||||
|
||||
// Title
|
||||
titleLabel = new Title("Choisissez un série", 60f, Color.WHITE);
|
||||
titleLabel = new Title("Choisissez une série", 60f, Color.WHITE);
|
||||
mainPanel.add(titleLabel, createGridBagConstraints(0, 0, 2));
|
||||
|
||||
mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 1, 1));
|
||||
@@ -76,6 +77,7 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
modePanel.setOpaque(false);
|
||||
seriesButtons = new ArrayList<>();
|
||||
|
||||
|
||||
// Pagination panel
|
||||
JPanel paginationPanel = createPaginationPanel();
|
||||
|
||||
@@ -87,9 +89,9 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
|
||||
mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 5, 1));
|
||||
|
||||
// Seed input and start button
|
||||
// Seed input and start button anchored at the bottom
|
||||
JPanel seedPanel = createSeedPanel(buttonListener);
|
||||
mainPanel.add(seedPanel, createGridBagConstraints(0, 6, 2));
|
||||
background.add(seedPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public void loadSeriesForCurrentPage() {
|
||||
@@ -104,27 +106,29 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
// Calculer le lendemain de la date de fin
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(endDate);
|
||||
cal.add(Calendar.DAY_OF_MONTH, 1); // Ajouter un jour pour obtenir le lendemain
|
||||
Date nextDay = cal.getTime(); // Le lendemain de endDate
|
||||
cal.add(Calendar.DAY_OF_MONTH, 1);
|
||||
Date nextDay = cal.getTime();
|
||||
|
||||
// Vérifier si la case à cocher est sélectionnée
|
||||
boolean onlyDeveloperCreated = developerSeriesCheckBox.isSelected();
|
||||
|
||||
// Get paginated series
|
||||
List<String> series = database.getSeriesByDateRangePaginated(startDate, nextDay,
|
||||
currentPage,
|
||||
itemsPerPage);
|
||||
List<String> series = database.getSeriesByDateRangePaginated(startDate, nextDay, currentPage, itemsPerPage, onlyDeveloperCreated);
|
||||
|
||||
// Si aucune série n'est trouvée pour la période donnée, afficher un message
|
||||
if (series.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this, "Aucune série pour la période donnée",
|
||||
"Avertissement", JOptionPane.WARNING_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this, "Aucune série pour la période donnée", "Avertissement", JOptionPane.WARNING_MESSAGE);
|
||||
currentPage = 1; // Reset current page to 1 if no series is available
|
||||
updatePageLabelAndButtons(1, 1); // Mettre à jour le label et désactiver les boutons
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate grid layout dimensions
|
||||
int buttonCount = series.size();
|
||||
int columns = Math.min(buttonCount, 5); // Maximum 5 buttons per row
|
||||
int columns = Math.min(buttonCount, 5);
|
||||
int rows = (int) Math.ceil((double) buttonCount / columns);
|
||||
|
||||
modePanel.setLayout(new GridLayout(rows, columns, 20, 10)); // Add spacing between buttons
|
||||
modePanel.setLayout(new GridLayout(rows, columns, 20, 10));
|
||||
|
||||
for (String seriesName : series) {
|
||||
JButton seriesButton = createGameModeButton(seriesName, buttonListener);
|
||||
@@ -133,13 +137,13 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
}
|
||||
|
||||
// Update page label
|
||||
int totalSeries = database.countSeriesByDateRange(startDate, nextDay);
|
||||
int totalSeries = database.countSeriesByDateRange(startDate, nextDay, onlyDeveloperCreated);
|
||||
int totalPages = (int) Math.ceil((double) totalSeries / itemsPerPage);
|
||||
pageLabel.setText("Page " + currentPage + " / " + totalPages);
|
||||
|
||||
// Enable/disable pagination buttons
|
||||
prevButton.setEnabled(currentPage > 1);
|
||||
nextButton.setEnabled(currentPage < totalPages);
|
||||
// Assurez-vous que totalPages est au moins 1
|
||||
totalPages = Math.max(totalPages, 1);
|
||||
currentPage = Math.min(currentPage, totalPages); // Assurez-vous que la page actuelle ne dépasse pas le nombre total de pages
|
||||
updatePageLabelAndButtons(currentPage, totalPages);
|
||||
|
||||
// Refresh the panel
|
||||
modePanel.revalidate();
|
||||
@@ -147,52 +151,108 @@ public class GameModeSelectionPanel extends JPanel {
|
||||
}
|
||||
|
||||
|
||||
private void updatePageLabelAndButtons(int currentPage, int totalPages) {
|
||||
pageLabel.setText("Page " + currentPage + " / " + totalPages);
|
||||
|
||||
// Enable/disable pagination buttons
|
||||
prevButton.setEnabled(currentPage > 1);
|
||||
nextButton.setEnabled(currentPage < totalPages);
|
||||
|
||||
// Show/Hide pagination buttons if there is only one page
|
||||
boolean multiplePages = totalPages > 1;
|
||||
prevButton.setVisible(multiplePages);
|
||||
nextButton.setVisible(multiplePages);
|
||||
pageLabel.setVisible(multiplePages);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private JPanel createDateFilterPanel() {
|
||||
JPanel datePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||
// Création du panneau de date avec un BoxLayout vertical pour un meilleur agencement
|
||||
JPanel datePanel = new JPanel();
|
||||
datePanel.setOpaque(false);
|
||||
datePanel.setLayout(new BoxLayout(datePanel, BoxLayout.Y_AXIS));
|
||||
|
||||
// Panneau contenant les spinners de date
|
||||
JPanel dateSpinnersPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
|
||||
dateSpinnersPanel.setOpaque(false);
|
||||
|
||||
JLabel startLabel = new JLabel("Date de début:");
|
||||
startLabel.setForeground(Color.WHITE);
|
||||
startLabel.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
|
||||
JLabel endLabel = new JLabel("Date de fin:");
|
||||
endLabel.setForeground(Color.WHITE);
|
||||
endLabel.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
|
||||
// Créer des spinners pour les dates de début et de fin
|
||||
// Créer les spinners pour les dates de début et de fin
|
||||
Calendar cal = Calendar.getInstance();
|
||||
Date endDate = cal.getTime();
|
||||
cal.add(Calendar.DAY_OF_YEAR, -30);
|
||||
Date startDate = cal.getTime();
|
||||
|
||||
SpinnerDateModel startDateModel = new SpinnerDateModel(
|
||||
startDate, // Date par défaut (30 jours avant aujourd'hui)
|
||||
null, // Pas de date minimale
|
||||
endDate, // Date maximale = aujourd'hui
|
||||
Calendar.DAY_OF_MONTH // Unité de changement
|
||||
);
|
||||
SpinnerDateModel startDateModel = new SpinnerDateModel(startDate, null, endDate, Calendar.DAY_OF_MONTH);
|
||||
startDateSpinner = new JSpinner(startDateModel);
|
||||
startDateSpinner.setEditor(new JSpinner.DateEditor(startDateSpinner, "yyyy-MM-dd"));
|
||||
startDateSpinner.setEditor(new JSpinner.DateEditor(startDateSpinner, "dd-MM-yyyy"));
|
||||
stylizeDateSpinner(startDateSpinner);
|
||||
|
||||
SpinnerDateModel endDateModel = new SpinnerDateModel(
|
||||
endDate, // Date par défaut = aujourd'hui
|
||||
null, // Pas de date minimale
|
||||
endDate, // Date maximale = aujourd'hui
|
||||
Calendar.DAY_OF_MONTH // Unité de changement
|
||||
);
|
||||
SpinnerDateModel endDateModel = new SpinnerDateModel(endDate, null, endDate, Calendar.DAY_OF_MONTH);
|
||||
endDateSpinner = new JSpinner(endDateModel);
|
||||
endDateSpinner.setEditor(new JSpinner.DateEditor(endDateSpinner, "yyyy-MM-dd"));
|
||||
endDateSpinner.setEditor(new JSpinner.DateEditor(endDateSpinner, "dd-MM-yyyy"));
|
||||
stylizeDateSpinner(endDateSpinner);
|
||||
|
||||
dateSpinnersPanel.add(startLabel);
|
||||
dateSpinnersPanel.add(startDateSpinner);
|
||||
dateSpinnersPanel.add(endLabel);
|
||||
dateSpinnersPanel.add(endDateSpinner);
|
||||
|
||||
// Ajouter la case à cocher pour les séries créées par les développeurs
|
||||
developerSeriesCheckBox = new JCheckBox("Inclure seulement les séries créées par les développeurs");
|
||||
developerSeriesCheckBox.setOpaque(false);
|
||||
developerSeriesCheckBox.setForeground(Color.WHITE);
|
||||
developerSeriesCheckBox.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
developerSeriesCheckBox.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
|
||||
// Créer un bouton de filtre
|
||||
JButton filterButton = new JButton("Filtrer");
|
||||
filterButton.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
filterButton.setBackground(new Color(70, 130, 180));
|
||||
filterButton.setForeground(Color.WHITE);
|
||||
filterButton.setFocusPainted(false);
|
||||
filterButton.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createLineBorder(new Color(255, 255, 255, 120), 2),
|
||||
BorderFactory.createEmptyBorder(5, 15, 5, 15)
|
||||
));
|
||||
filterButton.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
filterButton.addActionListener(new GameModeFilterButtonActionListener(this));
|
||||
|
||||
datePanel.add(startLabel);
|
||||
datePanel.add(startDateSpinner);
|
||||
datePanel.add(endLabel);
|
||||
datePanel.add(endDateSpinner);
|
||||
// Ajouter les composants au panneau principal de filtre
|
||||
datePanel.add(dateSpinnersPanel);
|
||||
datePanel.add(Box.createVerticalStrut(10));
|
||||
datePanel.add(developerSeriesCheckBox);
|
||||
datePanel.add(Box.createVerticalStrut(15));
|
||||
datePanel.add(filterButton);
|
||||
|
||||
return datePanel;
|
||||
}
|
||||
|
||||
private void stylizeDateSpinner(JSpinner spinner) {
|
||||
JComponent editor = spinner.getEditor();
|
||||
if (editor instanceof JSpinner.DefaultEditor) {
|
||||
JSpinner.DefaultEditor defaultEditor = (JSpinner.DefaultEditor) editor;
|
||||
JTextField textField = defaultEditor.getTextField();
|
||||
textField.setFont(new Font("Arial", Font.PLAIN, 16));
|
||||
textField.setBorder(BorderFactory.createCompoundBorder(
|
||||
BorderFactory.createLineBorder(new Color(255, 255, 255, 120), 2),
|
||||
BorderFactory.createEmptyBorder(5, 10, 5, 10)
|
||||
));
|
||||
textField.setBackground(new Color(40, 40, 40)); // Fond doux pour les spinners
|
||||
textField.setForeground(Color.WHITE); // Texte blanc pour une meilleure lisibilité
|
||||
textField.setCaretColor(Color.WHITE); // Curseur blanc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private JPanel createPaginationPanel() {
|
||||
JPanel paginationPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||
paginationPanel.setOpaque(false);
|
||||
|
@@ -5,6 +5,9 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JButton;
|
||||
|
||||
import fr.monkhanny.dorfromantik.enums.Sounds;
|
||||
import fr.monkhanny.dorfromantik.utils.MusicPlayer;
|
||||
|
||||
public class GameModeHoverEffectMouseListener extends MouseAdapter {
|
||||
private Color defaultColor;
|
||||
private Color hoverColor;
|
||||
@@ -20,6 +23,8 @@ public class GameModeHoverEffectMouseListener extends MouseAdapter {
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (e.getSource() instanceof JButton button) {
|
||||
button.setBackground(hoverColor);
|
||||
MusicPlayer.loadSound(Sounds.SOUNDS1); // Charge le son
|
||||
MusicPlayer.playSound(); // Joue le son
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -133,14 +133,19 @@ public class Database {
|
||||
}
|
||||
|
||||
// New method to count series within a date range
|
||||
public int countSeriesByDateRange(Date startDate, Date endDate) {
|
||||
public int countSeriesByDateRange(Date startDate, Date endDate, boolean onlyDeveloperCreated) {
|
||||
int count = 0;
|
||||
try {
|
||||
String query = "SELECT COUNT(*) as series_count FROM Series WHERE creation_date BETWEEN ? AND ?";
|
||||
// Construire la requête SQL en fonction du filtre "created_by_developer"
|
||||
String query = "SELECT COUNT(*) as series_count FROM Series WHERE creation_date BETWEEN ? AND ? " +
|
||||
(onlyDeveloperCreated ? "AND created_by_developer = TRUE " : "");
|
||||
|
||||
// Préparer l'instruction
|
||||
PreparedStatement statement = this.database.prepareStatement(query);
|
||||
statement.setDate(1, new java.sql.Date(startDate.getTime()));
|
||||
statement.setDate(2, new java.sql.Date(endDate.getTime()));
|
||||
|
||||
// Exécuter la requête et récupérer le résultat
|
||||
ResultSet resultSet = statement.executeQuery();
|
||||
if (resultSet.next()) {
|
||||
count = resultSet.getInt("series_count");
|
||||
@@ -151,20 +156,23 @@ public class Database {
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// New method to get paginated series within a date range
|
||||
public List<String> getSeriesByDateRangePaginated(Date startDate, Date endDate,
|
||||
int page, int itemsPerPage) {
|
||||
int page, int itemsPerPage,
|
||||
boolean onlyDeveloperCreated) {
|
||||
List<String> series = new ArrayList<>();
|
||||
try {
|
||||
String query = "SELECT name FROM Series " +
|
||||
"WHERE creation_date BETWEEN ? AND ? " +
|
||||
(onlyDeveloperCreated ? "AND created_by_developer = TRUE " : "") +
|
||||
"ORDER BY " +
|
||||
" CASE " +
|
||||
" WHEN name LIKE 'Série custom%' THEN CAST(REGEXP_SUBSTR(name, '[0-9]+') AS UNSIGNED) " + // Extraction numérique pour 'Série custom'
|
||||
" WHEN name LIKE 'Série custom%' THEN CAST(REGEXP_SUBSTR(name, '[0-9]+') AS UNSIGNED) " +
|
||||
" ELSE NULL " +
|
||||
" END ASC, " + // Tri par numéro pour 'Série custom'
|
||||
" created_by_developer DESC, " + // Tri par développeur ou joueur
|
||||
" name ASC " + // Tri alphabétique
|
||||
" END ASC, " +
|
||||
" created_by_developer DESC, " +
|
||||
" name ASC " +
|
||||
"LIMIT ? OFFSET ?";
|
||||
|
||||
PreparedStatement statement = this.database.prepareStatement(query);
|
||||
@@ -183,6 +191,7 @@ public class Database {
|
||||
return series;
|
||||
}
|
||||
|
||||
|
||||
// Optional: Method to get series within a specific number of days
|
||||
public List<String> getRecentSeries(int days) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
Reference in New Issue
Block a user