package gui.menu; import java.util.concurrent.CancellationException; import gui.widget.SudokuRenderer; import imgui.ImGui; import imgui.ImGuiStyle; import sudoku.io.SudokuSerializer; import sudoku.solver.BacktrackingSolver; import sudoku.solver.HumanSolver; import sudoku.solver.MixedSolver; import sudoku.solver.Solver; import sudoku.structure.MultiDoku; public class SudokuView extends BaseView { private final SudokuRenderer sudokuRenderer; private Thread resolveThread; private final MultiDoku doku; private String lastSavePath = null; private boolean resolved = false; public SudokuView(StateMachine stateMachine, MultiDoku doku) { super(stateMachine); this.doku = doku; this.sudokuRenderer = new SudokuRenderer(doku); this.sudokuRenderer.onResolve.connect(this::onResolve); } private void onResolve() { this.resolved = true; } private void stopResolve() { if (resolveThread != null && resolveThread.isAlive()) { resolveThread.interrupt(); resolveThread = null; } } boolean centeredButton(String label) { ImGuiStyle style = ImGui.getStyle(); float size = ImGui.calcTextSizeX(label) + style.getFramePaddingX() * 2.0f; float avail = ImGui.getContentRegionAvailX(); float off = (avail - size) * 0.5f; if (off > 0.0f) ImGui.setCursorPosX(ImGui.getCursorPosX() + off); return ImGui.button(label); } private void renderCancelButton() { boolean wantsToStop = false; if (resolveThread != null && resolveThread.isAlive()) { // ImGui.endDisabled(); if (centeredButton("Annuler")) { // we can't stop the Thread right now wantsToStop = true; } } if (resolveThread != null && !resolveThread.isAlive()) { resolveThread.start(); } if (wantsToStop) stopResolve(); } private void startSolve(Solver solver) { resolveThread = new Thread(() -> { try { solver.solve(this.doku); } catch (CancellationException e) { System.out.println("The user is bored !"); } stopResolve(); }); } private void renderSolvePopup() { if (ImGui.beginPopup("solve")) { if (ImGui.button("Résoudre avec backtrace")) { startSolve(new BacktrackingSolver()); ImGui.closeCurrentPopup(); } if (ImGui.button("Résoudre avec déduction")) { startSolve(new HumanSolver()); ImGui.closeCurrentPopup(); } if (ImGui.button("Résoudre avec déduction et backtrace")) { startSolve(new MixedSolver()); ImGui.closeCurrentPopup(); } ImGui.endPopup(); } } private void renderSolveButton() { if (resolveThread != null) ImGui.beginDisabled(); if (!this.resolved && centeredButton("Résoudre")) { // beginSolve = true; ImGui.openPopup("solve"); } if (resolveThread != null) ImGui.endDisabled(); if (this.resolved) { ImGui.text("Bravo !"); } renderSolvePopup(); } private void renderSaveButton() { if (ImGui.button("Sauvegarder l'état de la grille")) { lastSavePath = SudokuSerializer.saveMultiDoku(doku); ImGui.openPopup("saveDone"); } if (ImGui.beginPopup("saveDone")) { ImGui.text("Sudoku sauvegardé dans "); ImGui.text(lastSavePath); ImGui.endPopup(); } } @Override public void render() { sudokuRenderer.render(); renderSolveButton(); renderSaveButton(); renderCancelButton(); renderReturnButton(); } @Override public void closeMenu() { super.closeMenu(); stopResolve(); } }