Skip to content

Commit

Permalink
✨ New UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Xen0Xys committed Jul 10, 2023
1 parent 4db148f commit 10f5884
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 141 deletions.
2 changes: 1 addition & 1 deletion src/main/java/fr/xen0xys/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

public class Main {
public static void main(String[] args) {
GameWindow gameWindow = new GameWindow();
new GameWindow();
}
}
4 changes: 2 additions & 2 deletions src/main/java/fr/xen0xys/models/Computer.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
public class Computer {
private final Runner runner;

public Computer(AlgorithmType algorithmType, List<Rod> rods) {
public Computer(AlgorithmType algorithmType, List<Rod> rods, int tps) {
Algorithm algorithm;
switch (algorithmType){
case BUBBLE_SORT -> algorithm = new BubbleSort(this, rods);
case SELECTION_SORT -> algorithm = new SelectionSort(this, rods);
case INSERTION_SORT -> algorithm = new InsertionSort(this, rods);
default -> throw new IllegalStateException("Unexpected value: " + algorithmType);
}
this.runner = new Runner(algorithm::step, 20, true);
this.runner = new Runner(algorithm::step, tps, true);
}

public void start(){
Expand Down
16 changes: 13 additions & 3 deletions src/main/java/fr/xen0xys/models/algorithms/AlgorithmType.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package fr.xen0xys.models.algorithms;

public enum AlgorithmType {
BUBBLE_SORT,
SELECTION_SORT,
INSERTION_SORT
BUBBLE_SORT("Bubble Sort"),
SELECTION_SORT("Selection Sort"),
INSERTION_SORT("Insertion Sort");

private final String displayName;

AlgorithmType(String displayName) {
this.displayName = displayName;
}

public String getDisplayName() {
return displayName;
}
}
131 changes: 119 additions & 12 deletions src/main/java/fr/xen0xys/ui/GameWindow.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,142 @@
package fr.xen0xys.ui;

import fr.xen0xys.ui.views.MenuView;
import fr.xen0xys.models.Computer;
import fr.xen0xys.models.Rod;
import fr.xen0xys.models.algorithms.AlgorithmType;
import fr.xen0xys.ui.utils.Runner;
import fr.xen0xys.ui.views.AlgorithmPanel;
import fr.xen0xys.ui.views.MenuPanel;
import fr.xen0xys.utils.Tuple;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class GameWindow extends JFrame {
public class GameWindow extends JFrame implements ComponentListener {

private final MenuPanel menuPanel;
private final AlgorithmPanel algorithmPanel;
private final Runner graphicRunner;
private Computer computer;
private final List<Rod> rods;

public static final Font font = new Font("Roboto", Font.PLAIN, 18);

public GameWindow() {
super("Sorting Challenge");
this.rods = new ArrayList<>();
// Init panels and window
this.menuPanel = new MenuPanel(this);
this.algorithmPanel = new AlgorithmPanel(this, this.rods);
this.graphicRunner = new Runner(this.algorithmPanel::repaint, 60, true);
this.initWindow();
this.loadView(new MenuView(this));
this.setVisible(true);
this.generateRods(100);
this.graphicRunner.start();
}

private void initWindow(){
private void initWindow() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
// this.setResizable(false);
this.setLocationRelativeTo(null);
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException |
UnsupportedLookAndFeelException e) {
throw new RuntimeException(e);
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = screenSize.width - 50;
int height = screenSize.height - 300;
this.setLocation(25, 75);
this.resizePanels(width, height);
this.setSize(width + 15, height + 39);
this.setMinimumSize(new Dimension(1400, 675));
// Add panels to window
this.setLayout(null);
this.add(this.menuPanel);
this.add(this.algorithmPanel);
this.addComponentListener(this);
}

public Tuple<Integer, Integer> getRunnersAps() {
if (Objects.isNull(this.computer))
return new Tuple<>(this.graphicRunner.getCurrentAps(), -1);
return new Tuple<>(this.graphicRunner.getCurrentAps(), this.computer.getRunner().getCurrentAps());
}

private void resizePanels(int width, int height) {
int algorithmPanelHeight = (int) (height * 0.85);
int menuPanelHeight = height - algorithmPanelHeight;
this.algorithmPanel.setSize(width, algorithmPanelHeight);
this.algorithmPanel.setLocation(0, menuPanelHeight);
this.menuPanel.setSize(width, menuPanelHeight);
this.menuPanel.setLocation(0, 0);
}

@Override
public void componentResized(ComponentEvent e) {
this.resizePanels(this.getWidth() - 15, this.getHeight() - 39);
this.menuPanel.repaint();
}

@Override
public void componentMoved(ComponentEvent e) {

}

@Override
public void componentShown(ComponentEvent e) {

}

@Override
public void componentHidden(ComponentEvent e) {

}

private void generateRods(int rodCount) {
this.rods.clear();
for (int i = 0; i < rodCount; i++)
this.rods.add(new Rod(rodCount - i));
this.shuffle();
}

public void stopComputer() {
if(Objects.isNull(this.computer))
return;
this.computer.stop();
this.computer = null;
this.rods.forEach(rod -> rod.setColor(Color.WHITE));
}

public void startComputer(AlgorithmType algorithmType, int tps) {
if(Objects.nonNull(this.computer))
this.stopComputer();
this.computer = new Computer(algorithmType, this.rods, tps);
this.computer.start();
}

public void setFps(int fps) {
this.graphicRunner.setAps(fps);
}

public void setTps(int tps){
if(Objects.nonNull(this.computer))
this.computer.getRunner().setAps(tps);
}

public void setRodCount(int rodCount) {
if(Objects.nonNull(this.computer))
this.stopComputer();
this.generateRods(rodCount);
}

public void loadView(JPanel panel){
this.setContentPane(panel);
this.revalidate();
this.setSize(panel.getPreferredSize());
this.pack();
public void shuffle(){
this.stopComputer();
Collections.shuffle(this.rods);
}
}
22 changes: 18 additions & 4 deletions src/main/java/fr/xen0xys/ui/utils/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
public class Runner extends Thread{

private final Runnable action;
private final double aps;
private double aps;
private final boolean stability;

private boolean running = false;
private boolean paused = false;
private int passedActions = 0;
private final Queue<Long> apsQueue;
private Queue<Long> apsQueue;
private final ReentrantLock queueLock = new ReentrantLock();

/**
Expand All @@ -36,7 +36,7 @@ public Runner(@NotNull final Runnable action){
*/
public Runner(@NotNull final Runnable action, @Range(from = 0, to=10000) final int aps, final boolean stability){
this.action = action;
this.aps = 1D/aps;
this.aps = 1D / aps;
this.stability = stability;
this.apsQueue = EvictingQueue.create(aps);
}
Expand Down Expand Up @@ -67,7 +67,12 @@ public void run() {
}
Thread.yield();
}
this.apsQueue.clear();
this.queueLock.lock();
try {
this.apsQueue.clear();
} finally {
this.queueLock.unlock();
}
}

public void setPaused(boolean paused) {
Expand All @@ -76,6 +81,15 @@ public void setPaused(boolean paused) {
public void stopRunner(){
this.running = false;
}
public void setAps(int aps){
this.aps = 1D / aps;
this.queueLock.lock();
try {
this.apsQueue = EvictingQueue.create(aps);
} finally {
this.queueLock.unlock();
}
}

public boolean isRunning() {
return running;
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/fr/xen0xys/ui/views/AlgorithmPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package fr.xen0xys.ui.views;

import fr.xen0xys.models.Rod;
import fr.xen0xys.ui.GameWindow;
import fr.xen0xys.utils.Tuple;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.List;

public class AlgorithmPanel extends JPanel {

private final GameWindow window;
private final List<Rod> rods;

private final Rectangle2D rectangle2D = new Rectangle2D.Double(0, 0, 0, 0);

public AlgorithmPanel(GameWindow window, List<Rod> rods) {
this.window = window;
this.rods = rods;
this.initPanel();
}

private void initPanel(){
this.setBackground(Color.BLACK);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize.width - 50, screenSize.height - 150);
this.setPreferredSize(this.getSize());
this.setBorder(new EmptyBorder(0, 0, 0, 0));
}

@Override
protected void paintComponent(@NotNull final Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.setFont(GameWindow.font);
Tuple<Integer, Integer> runnersAps = this.window.getRunnersAps();
g2d.drawString("FPS : %d TPS : %d".formatted(runnersAps.first(), runnersAps.second()), 10, 25);
this.drawRods(g2d, this.rods);
}

private void drawRods(Graphics2D g, List<Rod> rods) {
if(rods.isEmpty()) return;
double spaceWidth = 1;
double spaces = rods.size() * spaceWidth;
double rodWidth = (this.getWidth() - spaces) / rods.size();
double maxRodHeight = this.getHeight() - 50;
for(int i = 0; i < rods.size(); i++){
Rod rod = rods.get(i);
double x = i * spaceWidth + i * rodWidth;
double height = maxRodHeight * rod.getValue() / rods.size();
double y = this.getHeight() - height;
g.setColor(rod.getColor());
rectangle2D.setRect(x, y, rodWidth, height);
g.fill(rectangle2D);
}
}
}
Loading

0 comments on commit 10f5884

Please sign in to comment.