diff --git a/src/main/java/edu/rpi/legup/app/Config.java b/src/main/java/edu/rpi/legup/app/Config.java index c5e51fb47..b03b01cb9 100644 --- a/src/main/java/edu/rpi/legup/app/Config.java +++ b/src/main/java/edu/rpi/legup/app/Config.java @@ -19,6 +19,7 @@ public class Config { private final static Logger Logger = LogManager.getLogger(Config.class.getName()); private Map puzzles; + private Map fileCreationDisabledStatuses; private static final String CONFIG_LOCATION = "edu/rpi/legup/legup/config"; /** @@ -27,7 +28,8 @@ public class Config { * @throws InvalidConfigException */ public Config() throws InvalidConfigException { - puzzles = new Hashtable<>(); + this.puzzles = new Hashtable<>(); + this.fileCreationDisabledStatuses = new Hashtable<>(); loadConfig(this.getClass().getClassLoader().getResourceAsStream(CONFIG_LOCATION)); } @@ -40,6 +42,16 @@ public List getPuzzleNames() { return new ArrayList<>(puzzles.keySet()); } + public List getFileCreationEnabledPuzzles() + { + LinkedList puzzles = new LinkedList(); + for (String puzzle : this.puzzles.keySet()) + if (!this.fileCreationDisabledStatuses.get(puzzle)) + puzzles.add(puzzle); + return puzzles; + } + + /** * Gets a {@link edu.rpi.legup.model.Puzzle} class for a puzzle name * @@ -77,8 +89,10 @@ private void loadConfig(InputStream stream) throws InvalidConfigException { Element puzzle = (Element) puzzleNodes.item(i); String name = puzzle.getAttribute("name"); String className = puzzle.getAttribute("qualifiedClassName"); + boolean status = Boolean.parseBoolean(puzzle.getAttribute("fileCreationDisabled").toLowerCase()); Logger.debug("Class Name: "+className); - puzzles.put(name, className); + this.puzzles.put(name, className); + this.fileCreationDisabledStatuses.put(name, Boolean.valueOf(status)); } } catch (ParserConfigurationException | SAXException | IOException e) { diff --git a/src/main/java/edu/rpi/legup/app/GameBoardFacade.java b/src/main/java/edu/rpi/legup/app/GameBoardFacade.java index fcae4df3d..240ccc090 100644 --- a/src/main/java/edu/rpi/legup/app/GameBoardFacade.java +++ b/src/main/java/edu/rpi/legup/app/GameBoardFacade.java @@ -6,6 +6,8 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.tree.Tree; +import edu.rpi.legup.ui.ProofEditorPanel; +import edu.rpi.legup.ui.PuzzleEditorPanel; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -42,6 +44,10 @@ public class GameBoardFacade implements IHistorySubject { private LegupUI legupUI; + private ProofEditorPanel puzzleSolver; + + private PuzzleEditorPanel puzzleEditor; + private String curFileName; private History history; @@ -73,20 +79,70 @@ public synchronized static GameBoardFacade getInstance() { public void initializeUI() { EventQueue.invokeLater(() ->{ legupUI = new LegupUI(); - addHistoryListener(legupUI); + puzzleSolver = legupUI.getProofEditor(); + puzzleEditor = legupUI.getPuzzleEditor(); + addHistoryListener(legupUI.getProofEditor()); + addHistoryListener(legupUI.getPuzzleEditor()); }); } public void setPuzzle(Puzzle puzzle) { this.puzzle = puzzle; - this.legupUI.setPuzzleView(puzzle); + this.puzzleSolver.setPuzzleView(puzzle); this.history.clear(); } + public void setPuzzleEditor(Puzzle puzzle) { + this.puzzle = puzzle; + this.puzzleEditor.setPuzzleView(puzzle); +// this.history.clear(); + } + public void setConfig(Config config) { this.config = config; } + /** + * Loads an empty puzzle + * + * @param game name of the puzzle + * @param rows the number of rows on the board + * @param columns the number of columns on the board + */ + public void loadPuzzle(String game, int rows, int columns) throws RuntimeException { + String qualifiedClassName = config.getPuzzleClassForName(game); + LOGGER.debug("Loading " + qualifiedClassName); + + try { + Class c = Class.forName(qualifiedClassName); + Constructor cons = c.getConstructor(); + Puzzle puzzle = (Puzzle) cons.newInstance(); + setWindowTitle(puzzle.getName(), "New " + puzzle.getName() + " Puzzle"); + + PuzzleImporter importer = puzzle.getImporter(); + if (importer == null) { + LOGGER.error("Puzzle importer is null"); + throw new RuntimeException("Puzzle importer null"); + } + + importer.initializePuzzle(rows, columns); + + puzzle.initializeView(); +// puzzle.getBoardView().onTreeElementChanged(puzzle.getTree().getRootNode()); + setPuzzleEditor(puzzle); + } + catch (IllegalArgumentException exception) + { + throw new IllegalArgumentException(exception.getMessage()); + } + catch(ClassNotFoundException | NoSuchMethodException | InvocationTargetException | + IllegalAccessException | InstantiationException e) + { + LOGGER.error(e); + throw new RuntimeException("Puzzle creation error"); + } + } + /** * Loads a puzzle file * diff --git a/src/main/java/edu/rpi/legup/app/PuzzleKeyAccelerator.java b/src/main/java/edu/rpi/legup/app/PuzzleKeyAccelerator.java index 6711e3035..e1a769610 100644 --- a/src/main/java/edu/rpi/legup/app/PuzzleKeyAccelerator.java +++ b/src/main/java/edu/rpi/legup/app/PuzzleKeyAccelerator.java @@ -7,8 +7,8 @@ import edu.rpi.legup.model.rules.ContradictionRule; import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.rules.RuleType; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import javax.swing.*; import java.awt.event.KeyEvent; @@ -16,9 +16,6 @@ import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import static edu.rpi.legup.app.GameBoardFacade.getInstance; public class PuzzleKeyAccelerator implements KeyListener { diff --git a/src/main/java/edu/rpi/legup/controller/EditorElementController.java b/src/main/java/edu/rpi/legup/controller/EditorElementController.java new file mode 100644 index 000000000..52aa67cfe --- /dev/null +++ b/src/main/java/edu/rpi/legup/controller/EditorElementController.java @@ -0,0 +1,43 @@ +package edu.rpi.legup.controller; + +import edu.rpi.legup.app.GameBoardFacade; +import edu.rpi.legup.app.LegupPreferences; +import edu.rpi.legup.history.*; +import edu.rpi.legup.model.Puzzle; +import edu.rpi.legup.model.elements.Element; +import edu.rpi.legup.model.gameboard.CaseBoard; +import edu.rpi.legup.model.rules.*; +import edu.rpi.legup.model.tree.TreeElement; +import edu.rpi.legup.model.tree.TreeElementType; +import edu.rpi.legup.ui.proofeditorui.rulesview.RuleButton; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeElementView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.puzzleeditorui.elementsview.ElementButton; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import static edu.rpi.legup.app.GameBoardFacade.getInstance; + +public class EditorElementController implements ActionListener { + protected Object lastSource; + + public EditorElementController() { + super(); + } + + public void buttonPressed(Element element) { + // TODO: implement what happens when element is pressed + } + + @Override + public void actionPerformed(ActionEvent e) { + lastSource = e.getSource(); + ElementButton button = (ElementButton) lastSource; + buttonPressed(button.getElement()); + } +} diff --git a/src/main/java/edu/rpi/legup/controller/ElementController.java b/src/main/java/edu/rpi/legup/controller/ElementController.java index a92cf0d2e..80f80db3e 100644 --- a/src/main/java/edu/rpi/legup/controller/ElementController.java +++ b/src/main/java/edu/rpi/legup/controller/ElementController.java @@ -15,7 +15,7 @@ import edu.rpi.legup.ui.boardview.ElementSelection; import edu.rpi.legup.ui.boardview.ElementView; import edu.rpi.legup.ui.boardview.SelectionItemView; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import edu.rpi.legup.history.ICommand; import edu.rpi.legup.history.EditDataCommand; diff --git a/src/main/java/edu/rpi/legup/controller/RuleController.java b/src/main/java/edu/rpi/legup/controller/RuleController.java index 84a32715f..12fef9b77 100644 --- a/src/main/java/edu/rpi/legup/controller/RuleController.java +++ b/src/main/java/edu/rpi/legup/controller/RuleController.java @@ -7,9 +7,9 @@ import edu.rpi.legup.model.gameboard.CaseBoard; import edu.rpi.legup.model.rules.*; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.rulesview.RuleButton; -import edu.rpi.legup.ui.rulesview.RulePanel; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.rulesview.RuleButton; +import edu.rpi.legup.ui.proofeditorui.rulesview.RulePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/src/main/java/edu/rpi/legup/controller/TreeController.java b/src/main/java/edu/rpi/legup/controller/TreeController.java index d695466fc..55306798b 100644 --- a/src/main/java/edu/rpi/legup/controller/TreeController.java +++ b/src/main/java/edu/rpi/legup/controller/TreeController.java @@ -3,7 +3,7 @@ import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.tree.Tree; import edu.rpi.legup.ui.boardview.BoardView; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import javax.swing.*; import java.awt.*; diff --git a/src/main/java/edu/rpi/legup/history/AddTreeElementCommand.java b/src/main/java/edu/rpi/legup/history/AddTreeElementCommand.java index 099af9afa..2f4733a55 100644 --- a/src/main/java/edu/rpi/legup/history/AddTreeElementCommand.java +++ b/src/main/java/edu/rpi/legup/history/AddTreeElementCommand.java @@ -2,11 +2,10 @@ import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.model.Puzzle; -import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.TreeElementView; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeElementView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/ApplyDefaultBasicRuleCommand.java b/src/main/java/edu/rpi/legup/history/ApplyDefaultBasicRuleCommand.java index 7284b8db2..a212ec602 100644 --- a/src/main/java/edu/rpi/legup/history/ApplyDefaultBasicRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ApplyDefaultBasicRuleCommand.java @@ -5,7 +5,7 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.rules.BasicRule; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java index 95b644102..c61875b74 100644 --- a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java @@ -7,7 +7,7 @@ import edu.rpi.legup.model.rules.CaseRule; import edu.rpi.legup.model.tree.*; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.awt.event.MouseEvent; import java.util.*; diff --git a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java index 9755d9002..4d78564de 100644 --- a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java +++ b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java @@ -4,7 +4,7 @@ import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.observer.ITreeListener; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/EditDataCommand.java b/src/main/java/edu/rpi/legup/history/EditDataCommand.java index 67e199934..f4c582220 100644 --- a/src/main/java/edu/rpi/legup/history/EditDataCommand.java +++ b/src/main/java/edu/rpi/legup/history/EditDataCommand.java @@ -7,7 +7,7 @@ import edu.rpi.legup.model.tree.*; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.awt.event.MouseEvent; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/MergeCommand.java b/src/main/java/edu/rpi/legup/history/MergeCommand.java index 0634906b7..e6ddf6dfb 100644 --- a/src/main/java/edu/rpi/legup/history/MergeCommand.java +++ b/src/main/java/edu/rpi/legup/history/MergeCommand.java @@ -5,7 +5,7 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.rules.MergeRule; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/ValidateBasicRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateBasicRuleCommand.java index d3d1eafb8..55c3421db 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateBasicRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateBasicRuleCommand.java @@ -2,11 +2,10 @@ import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.model.Puzzle; -import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.rules.BasicRule; import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/ValidateCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateCaseRuleCommand.java index 3697c2f2e..38672a555 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateCaseRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateCaseRuleCommand.java @@ -2,11 +2,10 @@ import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.model.Puzzle; -import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.rules.CaseRule; import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java index 258bb01c6..7033bbc3f 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java @@ -2,10 +2,9 @@ import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.model.Puzzle; -import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.rules.ContradictionRule; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/edu/rpi/legup/model/Puzzle.java b/src/main/java/edu/rpi/legup/model/Puzzle.java index 24fa967e1..a94f84b37 100644 --- a/src/main/java/edu/rpi/legup/model/Puzzle.java +++ b/src/main/java/edu/rpi/legup/model/Puzzle.java @@ -1,5 +1,7 @@ package edu.rpi.legup.model; +import edu.rpi.legup.model.elements.NonPlaceableElement; +import edu.rpi.legup.model.elements.PlaceableElement; import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.ElementFactory; import edu.rpi.legup.model.observer.IBoardListener; @@ -11,6 +13,7 @@ import edu.rpi.legup.model.tree.TreeElement; import edu.rpi.legup.model.tree.TreeElementType; import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.ui.puzzleeditorui.elementsview.NonPlaceableElementPanel; import edu.rpi.legup.utility.LegupUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -53,6 +56,8 @@ public abstract class Puzzle implements IBoardSubject, ITreeSubject { protected List basicRules; protected List contradictionRules; protected List caseRules; + protected List placeableElements; + protected List nonPlaceableElements; /** * Puzzle Constructor - creates a new Puzzle @@ -65,6 +70,9 @@ public Puzzle() { this.contradictionRules = new ArrayList<>(); this.caseRules = new ArrayList<>(); + this.placeableElements = new ArrayList<>(); + this.nonPlaceableElements = new ArrayList<>(); + registerRules(); } @@ -133,6 +141,15 @@ private void registerRules() { */ public abstract Board generatePuzzle(int difficulty); + /** + * Checks if the given height and width are valid board dimensions for the given puzzle + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @return true if the given dimensions are valid for the given puzzle, false otherwise + */ + public abstract boolean isValidDimensions(int rows, int columns); + /** * Determines if the edu.rpi.legup.puzzle was solves correctly * @@ -256,6 +273,13 @@ public String getName() { public List getBasicRules() { return basicRules; } + public List getPlaceableElements() { + return placeableElements; + } + public List getNonPlaceableElements() { + return nonPlaceableElements; + } + /** * Sets the list of basic rules @@ -274,7 +298,12 @@ public void setBasicRules(List basicRules) { public void addBasicRule(BasicRule rule) { basicRules.add(rule); } - + public void addPlaceableElement(PlaceableElement element) { + placeableElements.add(element); + } + public void addNonPlaceableElement(NonPlaceableElement element) { + nonPlaceableElements.add(element); + } /** * Remove a basic rule from this Puzzle * diff --git a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java index 0f73efa22..da15a62d4 100644 --- a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java +++ b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java @@ -29,6 +29,20 @@ public PuzzleImporter(Puzzle puzzle) { this.puzzle = puzzle; } + /** + * Initializes an empty puzzle + * + * @param rows number of rows on the puzzle + * @param columns number of columns on the puzzle + * @throws RuntimeException + */ + public void initializePuzzle(int rows, int columns) throws RuntimeException { + if (this.puzzle.isValidDimensions(rows, columns)) + initializeBoard(rows, columns); + else + throw new IllegalArgumentException("Invalid dimensions provided"); + } + /** * Initializes the puzzle attributes * @@ -80,6 +94,15 @@ public void initializePuzzle(Node node) throws InvalidFileFormatException { /** * Creates the board for building * + * @param rows number of rows on the puzzle + * @param columns number of columns on the puzzle + * @throws RuntimeException + */ + public abstract void initializeBoard(int rows, int columns); + + /** + * Creates an empty board for building + * * @param node xml document node * @throws InvalidFileFormatException */ diff --git a/src/main/java/edu/rpi/legup/model/elements/Element.java b/src/main/java/edu/rpi/legup/model/elements/Element.java new file mode 100644 index 000000000..0fdabe383 --- /dev/null +++ b/src/main/java/edu/rpi/legup/model/elements/Element.java @@ -0,0 +1,77 @@ +package edu.rpi.legup.model.elements; + +import edu.rpi.legup.model.rules.RuleType; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +public abstract class Element { + protected String elementID; + protected String elementName; + protected String description; + + protected String imageName; + protected ImageIcon image; + + protected ElementType elementType; + + private final String INVALID_USE_MESSAGE; + + public Element(String elementID, String elementName, String description, String imageName) { + this.elementID = elementID; + this.elementName = elementName; + this.description = description; + this.imageName = imageName; + this.INVALID_USE_MESSAGE = "Invalid use of the rule " + this.elementName; + loadImage(); + } + + private void loadImage() { + if (imageName != null) { + this.image = new ImageIcon(ClassLoader.getSystemResource(imageName)); + //Resize images to be 100px wide + Image image = this.image.getImage(); + if(this.image.getIconWidth() < 120) return; + int height = (int) (100 * ((double) this.image.getIconHeight() / this.image.getIconWidth())); + if(height==0){ + System.out.println("height is 0 error"); + System.out.println("height: "+this.image.getIconHeight()); + System.out.println("width: "+this.image.getIconWidth()); + return; + } + BufferedImage bimage = new BufferedImage(100, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g = bimage.createGraphics(); + g.drawImage(image, 0, 0, 100, height, null); + this.image = new ImageIcon(bimage); + } + } + public String getElementName() { + return elementName; + } + + public void setElementName(String elementName) { + this.elementName = elementName; + } + + public String getElementID() { + return elementID; + } + + public String getDescription() { + return description; + } + + public ImageIcon getImageIcon() { + return image; + } + + public ElementType getElementType() { + return elementType; + } + + public String getInvalidUseOfRuleMessage() + { + return this.INVALID_USE_MESSAGE; + } +} diff --git a/src/main/java/edu/rpi/legup/model/elements/ElementType.java b/src/main/java/edu/rpi/legup/model/elements/ElementType.java new file mode 100644 index 000000000..ea47ca0eb --- /dev/null +++ b/src/main/java/edu/rpi/legup/model/elements/ElementType.java @@ -0,0 +1,5 @@ +package edu.rpi.legup.model.elements; + +public enum ElementType { + PLACEABLE, NONPLACEABLE +} diff --git a/src/main/java/edu/rpi/legup/model/elements/NonPlaceableElement.java b/src/main/java/edu/rpi/legup/model/elements/NonPlaceableElement.java new file mode 100644 index 000000000..87859991f --- /dev/null +++ b/src/main/java/edu/rpi/legup/model/elements/NonPlaceableElement.java @@ -0,0 +1,8 @@ +package edu.rpi.legup.model.elements; + +public abstract class NonPlaceableElement extends Element { + public NonPlaceableElement(String elementID, String elementName, String description, String imageName) { + super(elementID, elementName, description, imageName); + this.elementType = ElementType.NONPLACEABLE; + } +} diff --git a/src/main/java/edu/rpi/legup/model/elements/PlaceableElement.java b/src/main/java/edu/rpi/legup/model/elements/PlaceableElement.java new file mode 100644 index 000000000..b22bdbf5e --- /dev/null +++ b/src/main/java/edu/rpi/legup/model/elements/PlaceableElement.java @@ -0,0 +1,8 @@ +package edu.rpi.legup.model.elements; + +public abstract class PlaceableElement extends Element{ + public PlaceableElement(String elementID, String elementName, String description, String imageName) { + super(elementID, elementName, description, imageName); + this.elementType = ElementType.PLACEABLE; + } +} diff --git a/src/main/java/edu/rpi/legup/model/observer/ITreeListener.java b/src/main/java/edu/rpi/legup/model/observer/ITreeListener.java index 89c48e25f..d8fa24166 100644 --- a/src/main/java/edu/rpi/legup/model/observer/ITreeListener.java +++ b/src/main/java/edu/rpi/legup/model/observer/ITreeListener.java @@ -1,7 +1,7 @@ package edu.rpi.legup.model.observer; import edu.rpi.legup.model.tree.TreeElement; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; public interface ITreeListener { /** diff --git a/src/main/java/edu/rpi/legup/puzzle/battleship/Battleship.java b/src/main/java/edu/rpi/legup/puzzle/battleship/Battleship.java index 7ddf25236..abcfbc3a9 100644 --- a/src/main/java/edu/rpi/legup/puzzle/battleship/Battleship.java +++ b/src/main/java/edu/rpi/legup/puzzle/battleship/Battleship.java @@ -31,6 +31,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Battleship + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Battleship, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java index 02035abf7..b05e5b1c9 100644 --- a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java @@ -13,6 +13,18 @@ public BattleshipImporter(Battleship battleShip) { super(battleShip); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java index 8d35d3931..cf6df4064 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java @@ -33,6 +33,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Fillapix + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Fillapix, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + @Override public boolean isBoardComplete(Board board) { FillapixBoard fillapixBoard = (FillapixBoard) board; diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java index 4bf28af2b..0be80324a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java @@ -13,6 +13,18 @@ public FillapixImporter(Fillapix fillapix) { super(fillapix); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/heyawake/Heyawake.java b/src/main/java/edu/rpi/legup/puzzle/heyawake/Heyawake.java index b28347e0a..951dd5c3e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/heyawake/Heyawake.java +++ b/src/main/java/edu/rpi/legup/puzzle/heyawake/Heyawake.java @@ -35,6 +35,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for HeyAwake + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for HeyAwake, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java index e72be136a..018246175 100644 --- a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java @@ -14,6 +14,18 @@ public HeyawakeImporter(Heyawake heyawake) { super(heyawake); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java index ed6007c65..0053335e2 100644 --- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java +++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java @@ -38,6 +38,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Light Up + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Light Up, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java index 625483090..aa8c8458c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java @@ -13,6 +13,18 @@ public LightUpImporter(LightUp lightUp) { super(lightUp); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/EditLineCommand.java b/src/main/java/edu/rpi/legup/puzzle/masyu/EditLineCommand.java index 493d5e1ad..8ff001d71 100644 --- a/src/main/java/edu/rpi/legup/puzzle/masyu/EditLineCommand.java +++ b/src/main/java/edu/rpi/legup/puzzle/masyu/EditLineCommand.java @@ -11,7 +11,7 @@ import edu.rpi.legup.model.tree.TreeTransition; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.*; +import edu.rpi.legup.ui.proofeditorui.treeview.*; import java.awt.event.MouseEvent; diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/Masyu.java b/src/main/java/edu/rpi/legup/puzzle/masyu/Masyu.java index 7ce783a6a..2134f1f90 100644 --- a/src/main/java/edu/rpi/legup/puzzle/masyu/Masyu.java +++ b/src/main/java/edu/rpi/legup/puzzle/masyu/Masyu.java @@ -36,6 +36,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Masyu + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Masyu, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java index 5e0b4ca57..0f96d59df 100644 --- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java @@ -13,6 +13,18 @@ public MasyuImporter(Masyu masyu) { super(masyu); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/Nurikabe.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/Nurikabe.java index 782df59f2..fbd0d3d88 100644 --- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/Nurikabe.java +++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/Nurikabe.java @@ -37,6 +37,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Nurikabe + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Nurikabe, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java index 82efff1c1..f9dfb98f5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java @@ -13,6 +13,18 @@ public NurikabeImporter(Nurikabe nurikabe) { super(nurikabe); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java index 62a39e870..e8a23b1e9 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java @@ -39,6 +39,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Short Truth Table + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Short Truth Table, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java index cbf052521..a372b9053 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java @@ -214,7 +214,17 @@ private void setGivenCells(ShortTruthTableBoard sttBoard, } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + } //STATEMENT IMPORTER diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/ClueCommand.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/ClueCommand.java index 6e350c6aa..d45d82c54 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/ClueCommand.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/ClueCommand.java @@ -2,23 +2,18 @@ import edu.rpi.legup.history.CommandError; import edu.rpi.legup.history.PuzzleCommand; -import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.TreeElementView; -import edu.rpi.legup.ui.treeview.TreeNodeView; -import edu.rpi.legup.ui.treeview.TreeTransitionView; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeElementView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeNodeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeTransitionView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static edu.rpi.legup.app.GameBoardFacade.getInstance; - public class ClueCommand extends PuzzleCommand { private TreeViewSelection selection; private SkyscrapersClueView clueView; diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java index 063804b07..b04fb5123 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java @@ -41,6 +41,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Skyscrapers + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Skyscrapers, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java index 45b8a3f0b..1a5664f94 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java @@ -10,9 +10,9 @@ import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.TreePanel; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.awt.event.MouseEvent; diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java index 1207845a8..727d9957e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java @@ -1,11 +1,8 @@ package edu.rpi.legup.puzzle.skyscrapers; -import edu.rpi.legup.app.LegupPreferences; -import edu.rpi.legup.puzzle.sudoku.SudokuCell; import edu.rpi.legup.ui.boardview.GridElementView; import java.awt.*; -import java.awt.geom.Rectangle2D; public class SkyscrapersElementView extends GridElementView { private static final Font FONT = new Font("TimesRoman", Font.BOLD, 16); diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java index 5ddcc673f..0f009a440 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java @@ -13,6 +13,18 @@ public SkyscrapersImporter(Skyscrapers treeTent) { super(treeTent); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/Sudoku.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/Sudoku.java index 2704ce314..f94d2290a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/sudoku/Sudoku.java +++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/Sudoku.java @@ -46,6 +46,33 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Sudoku + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Sudoku, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // The number of rows and columns must be greater than 1 + if (rows <= 1 || columns <= 1) + return false; + + // The number of rows and columns must be equal + if (rows != columns) + return false; + + // For Sudoku, the number of rows and columns must be a perfect square + // Note: we don't need to check the columns since by this point, we have verified that the number of rows + // equals the number of columns + double sqrtRows = Math.sqrt(rows); + if (sqrtRows - Math.floor(sqrtRows) != 0) + return false; + + return true; + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java index 0805da8f9..f94f516ba 100644 --- a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java @@ -13,6 +13,34 @@ public SudokuImporter(Sudoku sudoku) { super(sudoku); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + SudokuBoard sudokuBoard; + int minorSize = (int) Math.sqrt(rows); + sudokuBoard = new SudokuBoard(rows); + + for (int y = 0; y < columns; y++) { + for (int x = 0; x < rows; x++) { + if (sudokuBoard.getCell(x, y) == null) { + int groupIndex = x / minorSize + y / minorSize * minorSize; + SudokuCell cell = new SudokuCell(0, new Point(x, y), groupIndex, rows); + cell.setIndex(y * rows + x); + cell.setModifiable(true); + sudokuBoard.setCell(x, y, cell); + } + } + } + + puzzle.setCurrentBoard(sudokuBoard); + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuView.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuView.java index 4625c6c24..e0e099038 100644 --- a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuView.java +++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuView.java @@ -1,7 +1,6 @@ package edu.rpi.legup.puzzle.sudoku; import edu.rpi.legup.controller.BoardController; -import edu.rpi.legup.controller.ElementController; import edu.rpi.legup.ui.boardview.DataSelectionView; import edu.rpi.legup.ui.boardview.ElementView; import edu.rpi.legup.ui.boardview.GridBoardView; diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/ClueCommand.java b/src/main/java/edu/rpi/legup/puzzle/treetent/ClueCommand.java index 0ddf9ac29..5722774ef 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/ClueCommand.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/ClueCommand.java @@ -4,9 +4,9 @@ import edu.rpi.legup.history.PuzzleCommand; import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.tree.*; -import edu.rpi.legup.ui.treeview.TreeElementView; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeElementView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/EditLineCommand.java b/src/main/java/edu/rpi/legup/puzzle/treetent/EditLineCommand.java index 3a42f12da..ea03fc6f5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/EditLineCommand.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/EditLineCommand.java @@ -5,9 +5,9 @@ import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.tree.*; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.TreeElementView; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeElementView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.awt.*; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTent.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTent.java index 1599965bd..cf5fd5fdf 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTent.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTent.java @@ -36,6 +36,19 @@ public Board generatePuzzle(int difficulty) { return null; } + @Override + /** + * Determines if the given dimensions are valid for Tree Tent + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Tree Tent, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + // This is a placeholder, this method needs to be implemented + throw new UnsupportedOperationException(); + } + /** * Determines if the current board is a valid state * diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java index 833180ee3..1440ced35 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java @@ -10,9 +10,9 @@ import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.boardview.ElementView; -import edu.rpi.legup.ui.treeview.TreePanel; -import edu.rpi.legup.ui.treeview.TreeView; -import edu.rpi.legup.ui.treeview.TreeViewSelection; +import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import java.awt.event.MouseEvent; diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java index fdbef245e..68b8fdf70 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java @@ -13,6 +13,18 @@ public TreeTentImporter(TreeTent treeTent) { super(treeTent); } + /** + * Creates an empty board for building + * + * @param rows the number of rows on the board + * @param columns the number of columns on the board + * @throws RuntimeException + */ + @Override + public void initializeBoard(int rows, int columns) { + + } + /** * Creates the board for building * diff --git a/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java new file mode 100644 index 000000000..9f6d242fc --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java @@ -0,0 +1,100 @@ +package edu.rpi.legup.ui; + +import edu.rpi.legup.app.GameBoardFacade; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Arrays; + +public class CreatePuzzleDialog extends JDialog implements ActionListener { + private String[] games; + JComboBox gameBox; + JLabel puzzleLabel = new JLabel("Puzzle:"); + JButton ok = new JButton("Ok"); + JButton cancel = new JButton("Cancel"); + JTextField rows; + JTextField columns; + private HomePanel homePanel; + + public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) { + super(parent, true); + + this.homePanel = homePanel; + + initPuzzles(); + + Rectangle b = parent.getBounds(); + + setSize(350, 200); + setLocation((int) b.getCenterX() - getWidth() / 2, (int) b.getCenterY() - getHeight() / 2); + + Container c = getContentPane(); + c.setLayout(null); + + puzzleLabel.setBounds(10, 30, 70, 25); + gameBox.setBounds(80, 30, 190, 25); + + ok.setBounds(20, 130, 60, 25); + cancel.setBounds(170, 130, 90, 25); + + c.add(puzzleLabel); + c.add(gameBox); + + rows = new JTextField(); + columns = new JTextField(); + + JLabel rowsLabel = new JLabel("Rows:"); + JLabel columnsLabel = new JLabel("Columns:"); + + rowsLabel.setBounds(30, 70, 60, 25); + columnsLabel.setBounds(30, 95, 60, 25); + + rows.setBounds(100, 70, 60, 25); + columns.setBounds(100, 95, 60, 25); + + c.add(rowsLabel); + c.add(columnsLabel); + + c.add(rows); + c.add(columns); + + c.add(ok); + c.add(cancel); + + ok.addActionListener(this); + cancel.addActionListener(this); + } + + public void initPuzzles() { + this.games = GameBoardFacade.getInstance().getConfig().getFileCreationEnabledPuzzles().toArray(new String[0]); + Arrays.sort(this.games); + gameBox = new JComboBox(games); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == ok) { + String game = (String) gameBox.getSelectedItem(); + try + { + this.homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(this.rows.getText()), Integer.valueOf(this.columns.getText())); + setVisible(false); + } + catch (IllegalArgumentException exception) + { + // Don't do anything. This is here to prevent the dialog from closing if the dimensions are invalid. + } + } + else if (e.getSource() == cancel) { + setVisible(false); + } + } + + private boolean isValidDimensions() + { + // Needs to be implemented + return false; + } +} diff --git a/src/main/java/edu/rpi/legup/ui/HomePanel.java b/src/main/java/edu/rpi/legup/ui/HomePanel.java new file mode 100644 index 000000000..48ccea450 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/HomePanel.java @@ -0,0 +1,187 @@ +package edu.rpi.legup.ui; + +import javax.swing.*; +import java.awt.*; + +public class HomePanel extends LegupPanel { + private LegupUI legupUI; + private JFrame frame; + private JButton[] buttons; + private JLabel[] text; + private JMenuBar menuBar; + + private final int buttonSize = 100; + + public HomePanel(FileDialog fileDialog, JFrame frame, LegupUI legupUI) { + this.legupUI = legupUI; + this.frame = frame; + setLayout(new GridLayout(1, 2)); + initText(); + initButtons(); + } + + public JMenuBar getMenuBar() + { + this.menuBar = new JMenuBar(); + JMenu settings = new JMenu("Settings"); + menuBar.add(settings); + JMenuItem preferences = new JMenuItem("Preferences"); + preferences.addActionListener(a -> { System.out.println("Preferences clicked"); }); + settings.add(preferences); + + JMenuItem about = new JMenuItem("About"); + about.addActionListener(a -> { System.out.println("About clicked"); }); + settings.add(about); + + JMenuItem help = new JMenuItem("Help"); + about.addActionListener(a -> { System.out.println("Help clicked"); }); + settings.add(help); + + JMenuItem contribute = new JMenuItem("Contribute to Legup"); + contribute.addActionListener(a -> { System.out.println("Contribute to Legup clicked"); }); + settings.add(contribute); + + return this.menuBar; + } + + @Override + public void makeVisible() + { + render(); + frame.setJMenuBar(this.getMenuBar()); + } + + private static ImageIcon resizeButtonIcon(ImageIcon icon, int width, int height) + { + Image image = icon.getImage(); + Image resizedImage = image.getScaledInstance(width, height, Image.SCALE_SMOOTH); + return new ImageIcon(resizedImage); + } + + private void initButtons() { + this.buttons = new JButton[4]; + + this.buttons[0] = new JButton("Open Proof") + { + { + setSize(buttonSize, buttonSize); + setMaximumSize(getSize()); + } + }; + + ImageIcon button0Icon = new ImageIcon("src/main/resources/edu/rpi/legup/homepanel/openproof.png"); + this.buttons[0].setIcon(resizeButtonIcon(button0Icon, this.buttonSize, this.buttonSize)); + this.buttons[0].setHorizontalTextPosition(AbstractButton.CENTER); + this.buttons[0].setVerticalTextPosition(AbstractButton.BOTTOM); + this.buttons[0].addActionListener(l -> this.legupUI.displayPanel(1)); + + this.buttons[1] = new JButton("New Puzzle") + { + { + setSize(buttonSize, buttonSize); + setMaximumSize(getSize()); + } + }; + ImageIcon button1Icon = new ImageIcon("src/main/resources/edu/rpi/legup/homepanel/edit.png"); + this.buttons[1].setIcon(resizeButtonIcon(button1Icon, this.buttonSize, this.buttonSize)); + this.buttons[1].setHorizontalTextPosition(AbstractButton.CENTER); + this.buttons[1].setVerticalTextPosition(AbstractButton.BOTTOM); + this.buttons[1].addActionListener(l -> this.openNewPuzzleDialog()); + + this.buttons[2] = new JButton("Edit Puzzle") + { + { + setSize(buttonSize, buttonSize); + setMaximumSize(getSize()); + } + }; + ImageIcon button2Icon = new ImageIcon("src/main/resources/edu/rpi/legup/homepanel/edit.png"); // PLACEHOLDER + this.buttons[2].setIcon(resizeButtonIcon(button2Icon, this.buttonSize, this.buttonSize)); + this.buttons[2].setHorizontalTextPosition(AbstractButton.CENTER); + this.buttons[2].setVerticalTextPosition(AbstractButton.BOTTOM); + this.buttons[2].addActionListener(l -> this.legupUI.displayPanel(2)); // PLACEHOLDER + + for (int i = 0; i < this.buttons.length - 1; i++) // -1 to avoid the batch grader button + { + //this.buttons[i].setPreferredSize(new Dimension(100, 100)); + this.buttons[i].setBounds(200, 200, 700, 700); + } + + this.buttons[3] = new JButton("Batch Grader"); + this.buttons[3].setHorizontalTextPosition(AbstractButton.CENTER); + this.buttons[3].setVerticalTextPosition(AbstractButton.BOTTOM); + } + + private void initText() + { + this.text = new JLabel[3]; + + JLabel welcome = new JLabel("Welcome to Legup"); + welcome.setFont(new Font("Roboto", Font.BOLD, 23)); + welcome.setAlignmentX(Component.CENTER_ALIGNMENT); + + JLabel version = new JLabel("Version 3.0.0"); // This should be autochanged in the future + version.setFont(new Font("Roboto", Font.ITALIC, 10)); + version.setAlignmentX(Component.CENTER_ALIGNMENT); + + JLabel credits = new JLabel("A project by Dr. Bram van Heuveln"); + credits.setFont(new Font("Roboto", Font.PLAIN, 12)); + credits.setAlignmentX(Component.CENTER_ALIGNMENT); + + this.text[0] = welcome; + this.text[1] = version; + this.text[2] = credits; + } + + private void render() + { + this.removeAll(); + + this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + this.legupUI.setTitle("Legup: A Better Way to Learn Formal Logic"); + + JPanel buttons = new JPanel(); + buttons.add(Box.createRigidArea(new Dimension(5, 0))); + buttons.add(this.buttons[0]); + buttons.add(Box.createRigidArea(new Dimension(5, 0))); + buttons.add(this.buttons[1]); + buttons.add(Box.createRigidArea(new Dimension(5, 0))); + buttons.add(this.buttons[2]); + buttons.add(Box.createRigidArea(new Dimension(5, 0))); + + JPanel batchGraderButton = new JPanel(); + batchGraderButton.add(this.buttons[3]); + batchGraderButton.setAlignmentX(Component.LEFT_ALIGNMENT); + + this.add(Box.createRigidArea(new Dimension(0, 5))); + for (int i = 0; i < this.text.length; i++) + this.add(this.text[i]); + this.add(buttons); + this.add(batchGraderButton); + this.add(Box.createRigidArea(new Dimension(0, 5))); + } + + private void openNewPuzzleDialog() { + CreatePuzzleDialog cpd = new CreatePuzzleDialog(this.frame, this); + cpd.setVisible(true); + } + + public void openEditorWithNewPuzzle(String game, int width, int height) throws IllegalArgumentException { + // Set game type on the puzzle editor + try + { + this.legupUI.displayPanel(2); + this.legupUI.getPuzzleEditor().loadPuzzleFromHome(game, width, height); + } + catch (IllegalArgumentException exception) + { + this.legupUI.displayPanel(0); + JOptionPane.showMessageDialog(null, + "The dimensions you entered are invalid. Please double check \n" + + "the number of rows and columns and try again.", + "ERROR: Invalid Dimensions", + JOptionPane.ERROR_MESSAGE); + throw new IllegalArgumentException(exception.getMessage()); + } + } +} diff --git a/src/main/java/edu/rpi/legup/ui/LegupPanel.java b/src/main/java/edu/rpi/legup/ui/LegupPanel.java new file mode 100644 index 000000000..de5f70f76 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/LegupPanel.java @@ -0,0 +1,10 @@ +package edu.rpi.legup.ui; + +import javax.swing.*; + +public abstract class LegupPanel extends JPanel { + /** + * Alerts panel that it will be going visible now + */ + public abstract void makeVisible(); +} diff --git a/src/main/java/edu/rpi/legup/ui/LegupUI.java b/src/main/java/edu/rpi/legup/ui/LegupUI.java index b7fc18925..8bca7f663 100644 --- a/src/main/java/edu/rpi/legup/ui/LegupUI.java +++ b/src/main/java/edu/rpi/legup/ui/LegupUI.java @@ -3,114 +3,34 @@ import java.awt.*; import java.awt.event.*; import java.io.*; -import java.net.URI; -import java.net.URL; -import java.io.FileWriter; -import java.io.BufferedWriter; +import java.security.InvalidParameterException; +import java.util.Objects; import javax.swing.*; -import java.util.List; -import java.util.Objects; - import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.app.LegupPreferences; -import edu.rpi.legup.controller.BoardController; -import edu.rpi.legup.controller.RuleController; -import edu.rpi.legup.history.ICommand; -import edu.rpi.legup.history.IHistoryListener; -import edu.rpi.legup.model.tree.TreeNode; -import edu.rpi.legup.model.tree.TreeTransition; import edu.rpi.legup.ui.lookandfeel.LegupLookAndFeel; -import edu.rpi.legup.model.Puzzle; -import edu.rpi.legup.model.PuzzleExporter; -import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.tree.Tree; -import edu.rpi.legup.save.ExportFileException; -import edu.rpi.legup.save.InvalidFileFormatException; import edu.rpi.legup.ui.boardview.BoardView; -import edu.rpi.legup.ui.rulesview.RuleFrame; -import edu.rpi.legup.ui.treeview.TreePanel; -import edu.rpi.legup.ui.treeview.TreeViewSelection; -import edu.rpi.legup.user.Submission; +import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; import edu.rpi.legupupdate.Update; import edu.rpi.legupupdate.UpdateProgress; -import io.grpc.internal.KeepAliveManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import javax.swing.border.TitledBorder; - -public class LegupUI extends JFrame implements WindowListener, IHistoryListener { +public class LegupUI extends JFrame implements WindowListener { private final static Logger LOGGER = LogManager.getLogger(LegupUI.class.getName()); - public static final int ALLOW_HINTS = 1; - public static final int ALLOW_DEFAPP = 2; - public static final int ALLOW_FULLAI = 4; - public static final int ALLOW_JUST = 8; - public static final int REQ_STEP_JUST = 16; - public static final int IMD_FEEDBACK = 32; - public static final int INTERN_RO = 64; - public static final int AUTO_JUST = 128; - - final static int[] TOOLBAR_SEPARATOR_BEFORE = {2, 4, 8}; - private static final String[] PROFILES = {"No Assistance", "Rigorous Proof", "Casual Proof", "Assisted Proof", "Guided Proof", "Training-Wheels Proof", "No Restrictions"}; - private static final int[] PROF_FLAGS = {0, ALLOW_JUST | REQ_STEP_JUST, ALLOW_JUST, ALLOW_HINTS | ALLOW_JUST | AUTO_JUST, ALLOW_HINTS | ALLOW_JUST | REQ_STEP_JUST, ALLOW_HINTS | ALLOW_DEFAPP | ALLOW_JUST | IMD_FEEDBACK | INTERN_RO, ALLOW_HINTS | ALLOW_DEFAPP | ALLOW_FULLAI | ALLOW_JUST}; - - private static int CONFIG_INDEX = 0; - - protected JPanel contentPane; protected FileDialog fileDialog; - protected JFileChooser folderBrowser; - - protected PickGameDialog pickGameDialog; - protected JButton[] toolBarButtons; - - protected JMenuBar mBar; - - protected JMenu file; - protected JMenuItem newPuzzle, resetPuzzle, saveProof, preferences, exit; - - protected JMenu edit; - protected JMenuItem undo, redo; - - protected JMenu view; - - protected JMenu proof; - protected JMenuItem add, delete, merge, collapse; - protected JCheckBoxMenuItem allowDefault, caseRuleGen, imdFeedback; - - protected JMenu about; - protected JMenuItem checkUpdates, helpLegup, aboutLegup; - - protected JMenu proofMode = new JMenu("Proof Mode"); - protected JCheckBoxMenuItem[] proofModeItems = new JCheckBoxMenuItem[PROF_FLAGS.length]; - - protected JMenu ai = new JMenu("AI"); - protected JMenuItem runAI = new JMenuItem("Run AI to completion"); - protected JMenuItem setpAI = new JMenuItem("Run AI one Step"); - protected JMenuItem testAI = new JMenuItem("Test AI!"); - protected JMenuItem hintAI = new JMenuItem("Hint"); - - protected JMenu help; - - protected JToolBar toolBar; - - protected BoardView boardView; - protected DynamicView dynamicBoardView; - private RuleFrame ruleFrame; - private TreePanel treePanel; - - protected TitledBorder boardBorder; - - protected JSplitPane topHalfPanel, mainPanel; + protected JPanel window; + protected LegupPanel[] panels; /** * Identifies operating system */ - public String getOS() { + public static String getOS() { String os = System.getProperty("os.name").toLowerCase(); if(os.contains("mac")) os = "mac"; else os = "win"; @@ -130,16 +50,12 @@ public LegupUI() { System.err.println("Not supported ui look and feel"); } - this.contentPane = new JPanel(); - contentPane.setLayout(new BorderLayout()); - setContentPane(contentPane); + initPanels(); + displayPanel(0); setIconImage(new ImageIcon(Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource( "edu/rpi/legup/images/Legup/Basic Rules.gif"))).getImage()); - setupMenu(); - setupToolBar(); - setupContent(); if (LegupPreferences.getInstance().getUserPref(LegupPreferences.START_FULL_SCREEN).equals(Boolean.toString(true))) { setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH); } @@ -164,504 +80,45 @@ public void keyTyped(KeyEvent e) { setMinimumSize(getPreferredSize()); } - public static boolean profFlag(int flag) { - return !((PROF_FLAGS[CONFIG_INDEX] & flag) == 0); - } - - public void repaintTree() { - treePanel.repaintTreeView(GameBoardFacade.getInstance().getTree()); - } - - /** - * Sets up the menu bar - */ - private void setupMenu() { - mBar = new JMenuBar(); - fileDialog = new FileDialog(this); - - file = new JMenu("File"); - newPuzzle = new JMenuItem("Open"); - resetPuzzle = new JMenuItem("Reset Puzzle"); -// genPuzzle = new JMenuItem("Puzzle Generators"); - saveProof = new JMenuItem("Save Proof"); - preferences = new JMenuItem("Preferences"); - exit = new JMenuItem("Exit"); - - edit = new JMenu("Edit"); - undo = new JMenuItem("Undo"); - redo = new JMenuItem("Redo"); - - view = new JMenu("View"); - - proof = new JMenu("Proof"); - - String os = getOS(); - - add = new JMenuItem("Add"); - add.addActionListener(a -> treePanel.add()); - if(Objects.equals(os, "mac")) add.setAccelerator(KeyStroke.getKeyStroke('A', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else add.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.CTRL_DOWN_MASK)); - proof.add(add); - - delete = new JMenuItem("Delete"); - delete.addActionListener(a -> treePanel.delete()); - if(Objects.equals(os, "mac")) delete.setAccelerator(KeyStroke.getKeyStroke('D', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else delete.setAccelerator(KeyStroke.getKeyStroke('D', InputEvent.CTRL_DOWN_MASK)); - proof.add(delete); - - merge = new JMenuItem("Merge"); - merge.addActionListener(a -> treePanel.merge()); - if(Objects.equals(os, "mac")) merge.setAccelerator(KeyStroke.getKeyStroke('M', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else merge.setAccelerator(KeyStroke.getKeyStroke('M', InputEvent.CTRL_DOWN_MASK)); - proof.add(merge); - - collapse = new JMenuItem("Collapse"); - collapse.addActionListener(a -> treePanel.collapse()); - if(Objects.equals(os, "mac")) collapse.setAccelerator(KeyStroke.getKeyStroke('C', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else collapse.setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_DOWN_MASK)); - collapse.setEnabled(false); - proof.add(collapse); - - allowDefault = new JCheckBoxMenuItem("Allow Default Rule Applications", - LegupPreferences.getInstance().getUserPref(LegupPreferences.ALLOW_DEFAULT_RULES).equalsIgnoreCase(Boolean.toString(true))); - allowDefault.addChangeListener(e -> { - LegupPreferences.getInstance().setUserPref(LegupPreferences.ALLOW_DEFAULT_RULES, Boolean.toString(allowDefault.isSelected())); - }); - proof.add(allowDefault); - - caseRuleGen = new JCheckBoxMenuItem("Automatically generate cases for CaseRule", - LegupPreferences.getInstance().getUserPref(LegupPreferences.AUTO_GENERATE_CASES).equalsIgnoreCase(Boolean.toString(true))); - caseRuleGen.addChangeListener(e -> { - LegupPreferences.getInstance().setUserPref(LegupPreferences.AUTO_GENERATE_CASES, Boolean.toString(caseRuleGen.isSelected())); - }); - proof.add(caseRuleGen); - - imdFeedback = new JCheckBoxMenuItem("Provide immediate feedback", - LegupPreferences.getInstance().getUserPref(LegupPreferences.IMMEDIATE_FEEDBACK).equalsIgnoreCase(Boolean.toString(true))); - imdFeedback.addChangeListener(e -> { - LegupPreferences.getInstance().setUserPref(LegupPreferences.IMMEDIATE_FEEDBACK, Boolean.toString(imdFeedback.isSelected())); - }); - proof.add(imdFeedback); - - about = new JMenu("About"); - checkUpdates = new JMenuItem("Check for Updates..."); - helpLegup = new JMenuItem("Help Legup"); - aboutLegup = new JMenuItem("About Legup"); - - // unused - // help = new JMenu("Help"); - - mBar.add(file); - file.add(newPuzzle); - newPuzzle.addActionListener((ActionEvent) -> promptPuzzle()); - if(Objects.equals(os, "mac")) newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); - else newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK)); - -// file.add(genPuzzle); -//// genPuzzle.addActionListener((ActionEvent) -> -//// { -//// pickGameDialog = new PickGameDialog(this, true); -//// pickGameDialog.setVisible(true); -//// }); - file.add(resetPuzzle); - resetPuzzle.addActionListener(a -> { - Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); - if (puzzle != null) { - Tree tree = GameBoardFacade.getInstance().getTree(); - TreeNode rootNode = tree.getRootNode(); - if (rootNode != null) { - int confirmReset = JOptionPane.showConfirmDialog(this, "Reset Puzzle to Root Node?", "Confirm Reset", JOptionPane.YES_NO_CANCEL_OPTION); - if (confirmReset == JOptionPane.YES_OPTION) { - List children = rootNode.getChildren(); - children.forEach(t -> puzzle.notifyTreeListeners(l -> l.onTreeElementRemoved(t))); - final TreeViewSelection selection = new TreeViewSelection(treePanel.getTreeView().getElementView(rootNode)); - puzzle.notifyTreeListeners(l -> l.onTreeSelectionChanged(selection)); - GameBoardFacade.getInstance().getHistory().clear(); - } - } - } - }); - if(Objects.equals(os, "mac")) resetPuzzle.setAccelerator(KeyStroke.getKeyStroke('R', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else resetPuzzle.setAccelerator(KeyStroke.getKeyStroke('R', InputEvent.CTRL_DOWN_MASK)); - file.addSeparator(); - - file.add(saveProof); - saveProof.addActionListener((ActionEvent) -> saveProof()); - if(Objects.equals(os, "mac")) saveProof.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else saveProof.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK)); - - file.add(preferences); - preferences.addActionListener(a -> { - PreferencesDialog preferencesDialog = new PreferencesDialog(this); - }); - file.addSeparator(); - - file.add(exit); - exit.addActionListener((ActionEvent) -> System.exit(0)); - if(Objects.equals(os, "mac")) exit.setAccelerator(KeyStroke.getKeyStroke('Q', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else exit.setAccelerator(KeyStroke.getKeyStroke('Q', InputEvent.CTRL_DOWN_MASK)); - mBar.add(edit); - + private void initPanels() { + window = new JPanel(); + window.setLayout(new BorderLayout()); + add(window); + panels = new LegupPanel[3]; - edit.add(undo); - undo.addActionListener((ActionEvent) -> - { - GameBoardFacade.getInstance().getHistory().undo(); - }); - if(Objects.equals(os, "mac")) undo.setAccelerator(KeyStroke.getKeyStroke('Z', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - else undo.setAccelerator(KeyStroke.getKeyStroke('Z', InputEvent.CTRL_DOWN_MASK)); + panels[0] = new HomePanel(this.fileDialog, this, this); + panels[1] = new ProofEditorPanel(this.fileDialog, this, this); + panels[2] = new PuzzleEditorPanel(this.fileDialog, this, this); - edit.add(redo); - redo.addActionListener((ActionEvent) -> - { - GameBoardFacade.getInstance().getHistory().redo(); - }); - - if(Objects.equals(os, "mac")) redo.setAccelerator(KeyStroke.getKeyStroke('Z', Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() + InputEvent.SHIFT_DOWN_MASK)); - else redo.setAccelerator(KeyStroke.getKeyStroke('Z', InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); - - mBar.add(proof); - - about.add(checkUpdates); - checkUpdates.addActionListener(l -> { - checkUpdates(); - }); - checkUpdates.setEnabled(false); - - about.add(aboutLegup); - aboutLegup.addActionListener(l -> { - JOptionPane.showMessageDialog(null, "Version: 2.0.0"); - }); - - about.add(helpLegup); - helpLegup.addActionListener(l -> { - try { - java.awt.Desktop.getDesktop().browse(URI.create("https://github.com/jpoegs/Legup2.0")); - } catch (IOException e) { - LOGGER.error("Can't open web page"); - } - }); - - mBar.add(about); - - setJMenuBar(mBar); } - // contains all the code to setup the toolbar - private void setupToolBar() { - setToolBarButtons(new JButton[ToolbarName.values().length]); - for (int i = 0; i < ToolbarName.values().length; i++) { - String toolBarName = ToolbarName.values()[i].toString(); - URL resourceLocation = ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/" + toolBarName + ".png"); - assert resourceLocation != null; - JButton button = new JButton(toolBarName, new ImageIcon(resourceLocation)); - button.setFocusPainted(false); - getToolBarButtons()[i] = button; - } - - toolBar = new JToolBar(); - toolBar.setFloatable(false); - toolBar.setRollover(true); - - for (int i = 0; i < getToolBarButtons().length; i++) { - for (int j : TOOLBAR_SEPARATOR_BEFORE) { - if (i == j) { - toolBar.addSeparator(); - } - } - String toolBarName = ToolbarName.values()[i].toString(); - - toolBar.add(getToolBarButtons()[i]); - getToolBarButtons()[i].setToolTipText(toolBarName); - - getToolBarButtons()[i].setVerticalTextPosition(SwingConstants.BOTTOM); - getToolBarButtons()[i].setHorizontalTextPosition(SwingConstants.CENTER); + protected void displayPanel(int option) { + if (option > panels.length || option < 0) { + throw new InvalidParameterException("Invalid option"); } - -// toolBarButtons[ToolbarName.OPEN_PUZZLE.ordinal()].addActionListener((ActionEvent e) -> promptPuzzle()); -// toolBarButtons[ToolbarName.SAVE.ordinal()].addActionListener((ActionEvent e) -> saveProof()); -// toolBarButtons[ToolbarName.UNDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().undo()); -// toolBarButtons[ToolbarName.REDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().redo()); - toolBarButtons[ToolbarName.HINT.ordinal()].addActionListener((ActionEvent e) -> { - }); - toolBarButtons[ToolbarName.CHECK.ordinal()].addActionListener((ActionEvent e) -> checkProof()); - toolBarButtons[ToolbarName.SUBMIT.ordinal()].addActionListener((ActionEvent e) -> { - }); - toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].addActionListener((ActionEvent e) -> { - }); - - toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].addActionListener((ActionEvent e) -> checkProofAll()); - -// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(false); -// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); -// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.HINT.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.SUBMIT.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].setEnabled(true); - - contentPane.add(toolBar, BorderLayout.NORTH); - } - - /** - * Sets the main content for the edu.rpi.legup.user interface - */ - protected void setupContent() { -// JPanel consoleBox = new JPanel(new BorderLayout()); - JPanel treeBox = new JPanel(new BorderLayout()); - JPanel ruleBox = new JPanel(new BorderLayout()); - - RuleController ruleController = new RuleController(); - ruleFrame = new RuleFrame(ruleController); - ruleBox.add(ruleFrame, BorderLayout.WEST); - - treePanel = new TreePanel(this); - - dynamicBoardView = new DynamicView(new ScrollView(new BoardController())); - TitledBorder titleBoard = BorderFactory.createTitledBorder("Board"); - titleBoard.setTitleJustification(TitledBorder.CENTER); - dynamicBoardView.setBorder(titleBoard); - - JPanel boardPanel = new JPanel(new BorderLayout()); - topHalfPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, ruleFrame, dynamicBoardView); - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, topHalfPanel, treePanel); - topHalfPanel.setPreferredSize(new Dimension(600, 400)); - mainPanel.setPreferredSize(new Dimension(600, 600)); - - boardPanel.add(mainPanel); - boardBorder = BorderFactory.createTitledBorder("Board"); - boardBorder.setTitleJustification(TitledBorder.CENTER); - - ruleBox.add(boardPanel); - treeBox.add(ruleBox); - contentPane.add(treeBox); -// consoleBox.add(treeBox); -// -// getContentPane().add(consoleBox); - -// JPopupPanel popupPanel = new JPopupPanel(); -// setGlassPane(popupPanel); -// popupPanel.setVisible(true); - - mainPanel.setDividerLocation(mainPanel.getMaximumDividerLocation() + 100); + this.window.removeAll(); + panels[option].makeVisible(); + this.window.add(panels[option]); pack(); revalidate(); + repaint(); } - /** - * Saves a proof - */ - private void saveProof() { - Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); - if (puzzle == null) { - return; - } - - fileDialog.setMode(FileDialog.SAVE); - fileDialog.setTitle("Save Proof"); - String curFileName = GameBoardFacade.getInstance().getCurFileName(); - if (curFileName == null) { - fileDialog.setDirectory(LegupPreferences.getInstance().getUserPref(LegupPreferences.WORK_DIRECTORY)); - } else { - File curFile = new File(curFileName); - fileDialog.setDirectory(curFile.getParent()); - } - fileDialog.setVisible(true); - - String fileName = null; - if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { - fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); - } - - if (fileName != null) { - try { - PuzzleExporter exporter = puzzle.getExporter(); - if (exporter == null) { - throw new ExportFileException("Puzzle exporter null"); - } - exporter.exportPuzzle(fileName); - } catch (ExportFileException e) { - e.printStackTrace(); - } - } - } - - /** - * Checks the proof for correctness - */ - private void checkProof() { - GameBoardFacade facade = GameBoardFacade.getInstance(); - Tree tree = GameBoardFacade.getInstance().getTree(); - Board board = facade.getBoard(); - Board finalBoard = null; - boolean delayStatus = true; //board.evalDelayStatus(); - - repaintAll(); - - Puzzle puzzle = facade.getPuzzleModule(); - - if (puzzle.isPuzzleComplete()) { - // This is for submission which is not integrated yet - /*int confirm = JOptionPane.showConfirmDialog(null, "Congratulations! Your proof is correct. Would you like to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); - if (confirm == JOptionPane.YES_OPTION) { - Submission submission = new Submission(board); - submission.submit(); - }*/ - JOptionPane.showMessageDialog(null, "Congratulations! Your proof is correct."); - showStatus("Your proof is correct.", false); - } else { - String message = "\nThe game board is not solved."; - JOptionPane.showMessageDialog(null, message, "Invalid proof.", JOptionPane.ERROR_MESSAGE); - - showStatus(message, true); - } - } - - private void traverseDir(File folder, BufferedWriter writer, String path) throws IOException { - // Recursively traverse directory - GameBoardFacade facade = GameBoardFacade.getInstance(); - - // Folder is empty - if(Objects.requireNonNull(folder.listFiles()).length == 0) { - writer.append(path).append(",Empty folder,,Ungradeable\n"); - return; - } - - // Travese directory, recurse if sub-directory found - // If ungradeable, do not leave a score (0, 1) - for(final File f : Objects.requireNonNull(folder.listFiles())) { - // Recurse - if(f.isDirectory()) { - traverseDir(f, writer, path + "/" + f.getName()); - continue; - } - - // Set path name - writer.append(path).append(","); - - // Load puzzle, run checker - // If wrong file type, ungradeable - String fName = f.getName(); - String fPath = f.getAbsolutePath(); - File puzzleFile = new File(fPath); - if(puzzleFile.exists()) { - // Try to load file. If invalid, note in csv - try { - // Load puzzle, run checker - GameBoardFacade.getInstance().loadPuzzle(fPath); - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - setTitle(puzzleName + " - " + puzzleFile.getName()); - facade = GameBoardFacade.getInstance(); - Puzzle puzzle = facade.getPuzzleModule(); - - // Write data - writer.append(fName).append(","); - writer.append(puzzle.getName()).append(","); - if (puzzle.isPuzzleComplete()) - writer.append("1,Solved\n"); - else - writer.append("0,Unsolved\n"); - } catch (InvalidFileFormatException e) { - writer.append(fName).append(",Invalid,,Ungradeable\n"); - } - } else { - LOGGER.debug("Failed to run sim"); - } - } - } - - /** - * Checks the proof for all files - */ - private void checkProofAll() { - GameBoardFacade facade = GameBoardFacade.getInstance(); - - /* - * Select dir to grade; recursively grade sub-dirs using traverseDir() - * Selected dir must have sub-dirs for each student: - * GradeThis - * | - * | -> Student 1 - * | | - * | | -> Proofs - */ - folderBrowser = new JFileChooser(); - - folderBrowser.showOpenDialog(this); - folderBrowser.setVisible(true); - folderBrowser.setCurrentDirectory(new java.io.File(".")); - folderBrowser.setDialogTitle("Select Directory"); - folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - folderBrowser.setAcceptAllFileFilterUsed(false); - - File folder = folderBrowser.getSelectedFile(); - - // Write csv file (Path,File-Name,Puzzle-Type,Score,Solved?) - File resultFile = new File(folder.getAbsolutePath() + File.separator + "result.csv"); - try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) { - writer.append("Name,File Name,Puzzle Type,Score,Solved?\n"); - - // Go through student folders - for (final File folderEntry : Objects.requireNonNull(folder.listFiles(File::isDirectory))) { - // Write path - String path = folderEntry.getName(); - traverseDir(folderEntry, writer, path); - } - }catch (IOException ex){ - LOGGER.error(ex.getMessage()); - } - JOptionPane.showMessageDialog(null, "Batch grading complete."); + public ProofEditorPanel getProofEditor() { + return (ProofEditorPanel) panels[1]; } - - private boolean basicCheckProof(int[][] origCells) { - return false; + public PuzzleEditorPanel getPuzzleEditor() { + return (PuzzleEditorPanel) panels[2]; } - /** - * Submits the proof file - */ - private void submit() { - GameBoardFacade facade = GameBoardFacade.getInstance(); - Board board = facade.getBoard(); - boolean delayStatus = true; //board.evalDelayStatus(); - repaintAll(); - - Puzzle pm = facade.getPuzzleModule(); - if (pm.isPuzzleComplete()) { - // 0 means yes, 1 means no (Java's fault...) - int confirm = JOptionPane.showConfirmDialog(null, "Are you sure you wish to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); - if (confirm == 0) { - Submission submission = new Submission(board); - submission.submit(); - } - } else { - JOptionPane.showConfirmDialog(null, "Your proof is incorrect! Are you sure you wish to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); - Submission submit = new Submission(board); - } + public void repaintTree() { + getProofEditor().repaintTree(); } private void directions() { JOptionPane.showMessageDialog(null, "For every move you make, you must provide a rules for it (located in the Rules panel).\n" + "While working on the edu.rpi.legup.puzzle, you may click on the \"Check\" button to test your proof for correctness.", "Directions", JOptionPane.PLAIN_MESSAGE); } - private void showAll() { -// getToolBarButtons()[ToolbarName.SAVE.ordinal()].setEnabled(true); -// getToolBarButtons()[ToolbarName.UNDO.ordinal()].setEnabled(false); -// getToolBarButtons()[ToolbarName.REDO.ordinal()].setEnabled(false); - getToolBarButtons()[ToolbarName.HINT.ordinal()].setEnabled(true); - getToolBarButtons()[ToolbarName.CHECK.ordinal()].setEnabled(true); - getToolBarButtons()[ToolbarName.SUBMIT.ordinal()].setEnabled(true); - getToolBarButtons()[ToolbarName.DIRECTIONS.ordinal()].setEnabled(true); - - pack(); - } - - private void repaintAll() { - boardView.repaint(); - treePanel.repaint(); - } - public void showStatus(String status, boolean error) { showStatus(status, error, 1); } @@ -670,131 +127,10 @@ public void errorEncountered(String error) { JOptionPane.showMessageDialog(null, error); } - public void reloadGui() { - repaintTree(); - } - - public void promptPuzzle() { - GameBoardFacade facade = GameBoardFacade.getInstance(); - if (facade.getBoard() != null) { - if (noquit("Opening a new puzzle?")) // !noquit or noquit? - { - return; - } - } - - folderBrowser = new JFileChooser(); - - folderBrowser.showOpenDialog(this); - folderBrowser.setVisible(true); - folderBrowser.setCurrentDirectory(new java.io.File(".")); - folderBrowser.setDialogTitle("Select Directory"); - folderBrowser.setFileSelectionMode(JFileChooser.FILES_ONLY); - folderBrowser.setAcceptAllFileFilterUsed(true); - - String fileName = null; - File puzzleFile = folderBrowser.getSelectedFile(); - if (folderBrowser.getCurrentDirectory() != null && folderBrowser.getSelectedFile().getName() != null) { - fileName = puzzleFile.getAbsolutePath()+ File.separator; - puzzleFile = new File(fileName); - } - - if (puzzleFile != null && puzzleFile.exists()) { - try { - GameBoardFacade.getInstance().loadPuzzle(fileName); - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - setTitle(puzzleName + " - " + puzzleFile.getName()); - } catch (InvalidFileFormatException e) { - LOGGER.error(e.getMessage()); - if (e.getMessage().contains("Proof Tree construction error: could not find rule by ID")) // TO DO: make error message not hardcoded - JOptionPane.showMessageDialog(null, "This file runs on an outdated version of Legup\nand is not compatible with the current version.", "Error", JOptionPane.ERROR_MESSAGE); - else - JOptionPane.showMessageDialog(null, "File does not exist or it cannot be read", "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - public void showStatus(String status, boolean error, int timer) { // TODO: implement } - public void checkUpdates() { - String updateStr = null; - File jarPath = null; - try { - jarPath = new File(LegupUI.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile(); - } catch (Exception e) { - updateStr = "An error occurred while attempting to update Legup..."; - JOptionPane.showMessageDialog(this, updateStr, "Update Legup", JOptionPane.ERROR_MESSAGE); - } - Update update = new Update(Update.Stream.CLIENT, jarPath); - - boolean isUpdateAvailable = update.checkUpdate(); - int ans = 0; - if (isUpdateAvailable) { - updateStr = "There is update available. Do you want to update?"; - ans = JOptionPane.showConfirmDialog(this, updateStr, "Update Legup", JOptionPane.OK_CANCEL_OPTION); - } else { - updateStr = "There is no update available at this time. Check again later!"; - JOptionPane.showMessageDialog(this, updateStr, "Update Legup", JOptionPane.INFORMATION_MESSAGE); - } - - if (ans == JOptionPane.OK_OPTION && isUpdateAvailable) { - LOGGER.info("Updating Legup...."); - - new Thread(() -> { - JDialog updateDialog = new JDialog(this, "Updating Legup...", true); - JProgressBar dpb = new JProgressBar(0, 500); - updateDialog.add(BorderLayout.CENTER, dpb); - updateDialog.add(BorderLayout.NORTH, new JLabel("Progress...")); - updateDialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); - updateDialog.setSize(300, 75); - updateDialog.setResizable(false); - updateDialog.setLocationRelativeTo(this); -// updateDialog.setVisible(true); - update.setUpdateProgress(new UpdateProgress() { - double total = 0; - - @Override - public void setTotalDownloads(double total) { - this.total = total; - dpb.setString("0 - " + total); - } - - @Override - public void setCurrentDownload(double current) { - dpb.setValue((int) (current / total * 100)); - dpb.setString(current + " - " + total); - } - - @Override - public void setDescription(String description) { - - } - }); - update.update(); - }).start(); - } /*else { -// if (SystemUtils.IS_OS_WINDOWS) { -// File java = new File(SystemUtils.JAVA_HOME); -// java = new File(java, "bin"); -// java = new File(java, "javaw.exe"); -// String javaPath = java.getPath(); -// String legupPath = LegupUI.class.getProtectionDomain().getCodeSource().getLocation().getPath(); -// try { -// LOGGER.severe("starting new legup"); -// Process process = Runtime.getRuntime().exec(new String[]{javaPath, "-jar", legupPath}); -// process.waitFor(); -// System.out.println(new String(process.getInputStream().readAllBytes())); -// System.err.println(new String(process.getErrorStream().readAllBytes())); -// -// } catch (InterruptedException | IOException e) { -// LOGGER.severe("interrupted or io"); -// } -// } - }*/ - } - //ask to edu.rpi.legup.save current proof public boolean noquit(String instr) { int n = JOptionPane.showConfirmDialog(null, instr, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION); @@ -838,134 +174,15 @@ public void windowDeactivated(WindowEvent e) { } - /** - * Gets the toolbar buttons - * - * @return toolbar buttons - */ - public JButton[] getToolBarButtons() { - return toolBarButtons; - } - - /** - * Sets the toolbar buttons - * - * @param toolBarButtons toolbar buttons - */ - public void setToolBarButtons(JButton[] toolBarButtons) { - this.toolBarButtons = toolBarButtons; - } - - public void setPuzzleView(Puzzle puzzle) { - this.boardView = puzzle.getBoardView(); - - dynamicBoardView = new DynamicView(boardView); - this.topHalfPanel.setRightComponent(dynamicBoardView); - this.topHalfPanel.setVisible(true); - String boardType = boardView.getBoard().getClass().getSimpleName(); - boardType = boardType.substring(0, boardType.indexOf("Board")); - TitledBorder titleBoard = BorderFactory.createTitledBorder(boardType + " Board"); - titleBoard.setTitleJustification(TitledBorder.CENTER); - dynamicBoardView.setBorder(titleBoard); - - this.treePanel.getTreeView().resetView(); - this.treePanel.getTreeView().setTree(puzzle.getTree()); - - puzzle.addTreeListener(treePanel.getTreeView()); - puzzle.addBoardListener(puzzle.getBoardView()); - - ruleFrame.getBasicRulePanel().setRules(puzzle.getBasicRules()); - ruleFrame.getCasePanel().setRules(puzzle.getCaseRules()); - ruleFrame.getContradictionPanel().setRules(puzzle.getContradictionRules()); - - toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true); -// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(true); - - reloadGui(); - } - public BoardView getBoardView() { - return boardView; + return getProofEditor().getBoardView(); } public DynamicView getDynamicBoardView() { - return dynamicBoardView; + return getProofEditor().getDynamicBoardView(); } public TreePanel getTreePanel() { - return treePanel; - } - - /** - * Called when a action is pushed onto the edu.rpi.legup.history stack - * - * @param command action to push onto the stack - */ - @Override - public void onPushChange(ICommand command) { - LOGGER.info("Pushing " + command.getClass().getSimpleName() + " to stack."); - undo.setEnabled(true); -// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(true); - redo.setEnabled(false); -// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); - - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); - setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); - } - - /** - * Called when an action is undone - * - * @param isBottom true if there are no more actions to undo, false otherwise - * @param isTop true if there are no more changes to redo, false otherwise - */ - @Override - public void onUndo(boolean isBottom, boolean isTop) { - undo.setEnabled(!isBottom); -// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); - redo.setEnabled(!isTop); -// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); - if (isBottom) { - setTitle(puzzleName + " - " + puzzleFile.getName()); - } else { - setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); - } - } - - /** - * Called when an action is redone - * - * @param isBottom true if there are no more actions to undo, false otherwise - * @param isTop true if there are no more changes to redo, false otherwise - */ - @Override - public void onRedo(boolean isBottom, boolean isTop) { - undo.setEnabled(!isBottom); -// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); - redo.setEnabled(!isTop); -// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); - if (isBottom) { - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); - setTitle(puzzleName + " - " + puzzleFile.getName()); - } else { - String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); - File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); - setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); - } - } - - /** - * Called when the history is cleared - */ - @Override - public void onClearHistory() { - undo.setEnabled(false); -// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); - redo.setEnabled(false); -// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + return getProofEditor().getTreePanel(); } } diff --git a/src/main/java/edu/rpi/legup/ui/PreferencesDialog.java b/src/main/java/edu/rpi/legup/ui/PreferencesDialog.java index 8c5fae3b0..78d6cf72d 100644 --- a/src/main/java/edu/rpi/legup/ui/PreferencesDialog.java +++ b/src/main/java/edu/rpi/legup/ui/PreferencesDialog.java @@ -36,8 +36,8 @@ public class PreferencesDialog extends JDialog { } } - public PreferencesDialog(LegupUI legupUI) { - super(legupUI); + public PreferencesDialog(Frame frame) { + super(frame); setTitle("Preferences"); @@ -76,7 +76,7 @@ public PreferencesDialog(LegupUI legupUI) { setContentPane(mainPanel); setSize(600, 400); - setLocationRelativeTo(legupUI); + setLocationRelativeTo(frame); setVisible(true); } diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java new file mode 100644 index 000000000..ffeaa994b --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -0,0 +1,763 @@ +package edu.rpi.legup.ui; + +import edu.rpi.legup.app.GameBoardFacade; +import edu.rpi.legup.app.LegupPreferences; +import edu.rpi.legup.controller.BoardController; +import edu.rpi.legup.controller.RuleController; +import edu.rpi.legup.history.ICommand; +import edu.rpi.legup.history.IHistoryListener; +import edu.rpi.legup.model.Puzzle; +import edu.rpi.legup.model.PuzzleExporter; +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.tree.Tree; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.save.ExportFileException; +import edu.rpi.legup.save.InvalidFileFormatException; +import edu.rpi.legup.ui.boardview.BoardView; +import edu.rpi.legup.ui.proofeditorui.rulesview.RuleFrame; +import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; +import edu.rpi.legup.user.Submission; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.List; +import java.util.Objects; + +public class ProofEditorPanel extends LegupPanel implements IHistoryListener { + private final static Logger LOGGER = LogManager.getLogger(ProofEditorPanel.class.getName()); + private JMenuBar mBar; + private TreePanel treePanel; + private FileDialog fileDialog; + private JFrame frame; + private RuleFrame ruleFrame; + private DynamicView dynamicBoardView; + private JSplitPane topHalfPanel, mainPanel; + private TitledBorder boardBorder; + + private JButton[] toolBarButtons; + private JMenu file; + private JMenuItem newPuzzle, resetPuzzle, saveProof, preferences, exit; + private JMenu edit; + private JMenuItem undo, redo; + + private JMenu view; + + private JMenu proof; + private JMenuItem add, delete, merge, collapse; + private JCheckBoxMenuItem allowDefault, caseRuleGen, imdFeedback; + + private JMenu about, help; + private JMenuItem helpLegup, aboutLegup; + + private JToolBar toolBar; + private BoardView boardView; + private JFileChooser folderBrowser; + + private LegupUI legupUI; + + public static final int ALLOW_HINTS = 1; + public static final int ALLOW_DEFAPP = 2; + public static final int ALLOW_FULLAI = 4; + public static final int ALLOW_JUST = 8; + public static final int REQ_STEP_JUST = 16; + public static final int IMD_FEEDBACK = 32; + public static final int INTERN_RO = 64; + public static final int AUTO_JUST = 128; + final static int[] TOOLBAR_SEPARATOR_BEFORE = {2, 4, 8}; + private static final String[] PROFILES = {"No Assistance", "Rigorous Proof", "Casual Proof", "Assisted Proof", "Guided Proof", "Training-Wheels Proof", "No Restrictions"}; + private static final int[] PROF_FLAGS = {0, ALLOW_JUST | REQ_STEP_JUST, ALLOW_JUST, ALLOW_HINTS | ALLOW_JUST | AUTO_JUST, ALLOW_HINTS | ALLOW_JUST | REQ_STEP_JUST, ALLOW_HINTS | ALLOW_DEFAPP | ALLOW_JUST | IMD_FEEDBACK | INTERN_RO, ALLOW_HINTS | ALLOW_DEFAPP | ALLOW_FULLAI | ALLOW_JUST}; + private JMenu proofMode = new JMenu("Proof Mode"); + private JCheckBoxMenuItem[] proofModeItems = new JCheckBoxMenuItem[PROF_FLAGS.length]; + + private static int CONFIG_INDEX = 0; + + protected JMenu ai = new JMenu("AI"); + protected JMenuItem runAI = new JMenuItem("Run AI to completion"); + protected JMenuItem setpAI = new JMenuItem("Run AI one Step"); + protected JMenuItem testAI = new JMenuItem("Test AI!"); + protected JMenuItem hintAI = new JMenuItem("Hint"); + + public ProofEditorPanel(FileDialog fileDialog, JFrame frame, LegupUI legupUI) { + this.fileDialog = fileDialog; + this.frame = frame; + this.legupUI = legupUI; + setLayout(new BorderLayout()); + } + + @Override + public void makeVisible() { + this.removeAll(); + + setupToolBar(); + setupContent(); + frame.setJMenuBar(getMenuBar()); + } + + public JMenuBar getMenuBar() { + if(mBar != null) return mBar; + mBar = new JMenuBar(); + + file = new JMenu("File"); + newPuzzle = new JMenuItem("Open"); + resetPuzzle = new JMenuItem("Reset Puzzle"); +// genPuzzle = new JMenuItem("Puzzle Generators"); + saveProof = new JMenuItem("Save Proof"); + preferences = new JMenuItem("Preferences"); + exit = new JMenuItem("Exit"); + + edit = new JMenu("Edit"); + undo = new JMenuItem("Undo"); + redo = new JMenuItem("Redo"); + + view = new JMenu("View"); + + proof = new JMenu("Proof"); + + String os = LegupUI.getOS(); + + add = new JMenuItem("Add"); + add.addActionListener(a -> treePanel.add()); + if(os.equals("mac")) add.setAccelerator(KeyStroke.getKeyStroke('A', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else add.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.CTRL_DOWN_MASK)); + proof.add(add); + + delete = new JMenuItem("Delete"); + delete.addActionListener(a -> treePanel.delete()); + if(os.equals("mac")) delete.setAccelerator(KeyStroke.getKeyStroke('D', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else delete.setAccelerator(KeyStroke.getKeyStroke('D', InputEvent.CTRL_DOWN_MASK)); + proof.add(delete); + + merge = new JMenuItem("Merge"); + merge.addActionListener(a -> treePanel.merge()); + if(os.equals("mac")) merge.setAccelerator(KeyStroke.getKeyStroke('M', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else merge.setAccelerator(KeyStroke.getKeyStroke('M', InputEvent.CTRL_DOWN_MASK)); + proof.add(merge); + + collapse = new JMenuItem("Collapse"); + collapse.addActionListener(a -> treePanel.collapse()); + if(os.equals("mac")) collapse.setAccelerator(KeyStroke.getKeyStroke('C', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else collapse.setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_DOWN_MASK)); + collapse.setEnabled(false); + proof.add(collapse); + + allowDefault = new JCheckBoxMenuItem("Allow Default Rule Applications", + LegupPreferences.getInstance().getUserPref(LegupPreferences.ALLOW_DEFAULT_RULES).equalsIgnoreCase(Boolean.toString(true))); + allowDefault.addChangeListener(e -> { + LegupPreferences.getInstance().setUserPref(LegupPreferences.ALLOW_DEFAULT_RULES, Boolean.toString(allowDefault.isSelected())); + }); + proof.add(allowDefault); + + caseRuleGen = new JCheckBoxMenuItem("Automatically generate cases for CaseRule", + LegupPreferences.getInstance().getUserPref(LegupPreferences.AUTO_GENERATE_CASES).equalsIgnoreCase(Boolean.toString(true))); + caseRuleGen.addChangeListener(e -> { + LegupPreferences.getInstance().setUserPref(LegupPreferences.AUTO_GENERATE_CASES, Boolean.toString(caseRuleGen.isSelected())); + }); + proof.add(caseRuleGen); + + imdFeedback = new JCheckBoxMenuItem("Provide immediate feedback", + LegupPreferences.getInstance().getUserPref(LegupPreferences.IMMEDIATE_FEEDBACK).equalsIgnoreCase(Boolean.toString(true))); + imdFeedback.addChangeListener(e -> { + LegupPreferences.getInstance().setUserPref(LegupPreferences.IMMEDIATE_FEEDBACK, Boolean.toString(imdFeedback.isSelected())); + }); + proof.add(imdFeedback); + + about = new JMenu("About"); + helpLegup = new JMenuItem("Help Legup"); + aboutLegup = new JMenuItem("About Legup"); + + // unused + // help = new JMenu("Help"); + + mBar.add(file); + file.add(newPuzzle); + newPuzzle.addActionListener((ActionEvent) -> promptPuzzle()); + if(os.equals("mac")) newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK)); + +// file.add(genPuzzle); +//// genPuzzle.addActionListener((ActionEvent) -> +//// { +//// pickGameDialog = new PickGameDialog(this, true); +//// pickGameDialog.setVisible(true); +//// }); + file.add(resetPuzzle); + resetPuzzle.addActionListener(a -> { + Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); + if (puzzle != null) { + Tree tree = GameBoardFacade.getInstance().getTree(); + TreeNode rootNode = tree.getRootNode(); + if (rootNode != null) { + int confirmReset = JOptionPane.showConfirmDialog(this, "Reset Puzzle to Root Node?", "Confirm Reset", JOptionPane.YES_NO_CANCEL_OPTION); + if (confirmReset == JOptionPane.YES_OPTION) { + List children = rootNode.getChildren(); + children.forEach(t -> puzzle.notifyTreeListeners(l -> l.onTreeElementRemoved(t))); + final TreeViewSelection selection = new TreeViewSelection(treePanel.getTreeView().getElementView(rootNode)); + puzzle.notifyTreeListeners(l -> l.onTreeSelectionChanged(selection)); + GameBoardFacade.getInstance().getHistory().clear(); + } + } + } + }); + if(os.equals("mac")) resetPuzzle.setAccelerator(KeyStroke.getKeyStroke('R', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else resetPuzzle.setAccelerator(KeyStroke.getKeyStroke('R', InputEvent.CTRL_DOWN_MASK)); + file.addSeparator(); + + file.add(saveProof); + saveProof.addActionListener((ActionEvent) -> saveProof()); + if(os.equals("mac")) saveProof.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else saveProof.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK)); + + file.add(preferences); + preferences.addActionListener(a -> { + PreferencesDialog preferencesDialog = new PreferencesDialog(this.frame); + }); + file.addSeparator(); + + file.add(exit); + exit.addActionListener((ActionEvent) -> this.legupUI.displayPanel(0)); + if(os.equals("mac")) exit.setAccelerator(KeyStroke.getKeyStroke('Q', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else exit.setAccelerator(KeyStroke.getKeyStroke('Q', InputEvent.CTRL_DOWN_MASK)); + mBar.add(edit); + + + edit.add(undo); + undo.addActionListener((ActionEvent) -> + { + GameBoardFacade.getInstance().getHistory().undo(); + }); + if(os.equals("mac")) undo.setAccelerator(KeyStroke.getKeyStroke('Z', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else undo.setAccelerator(KeyStroke.getKeyStroke('Z', InputEvent.CTRL_DOWN_MASK)); + + edit.add(redo); + redo.addActionListener((ActionEvent) -> + { + GameBoardFacade.getInstance().getHistory().redo(); + }); + if(os.equals("mac")) redo.setAccelerator(KeyStroke.getKeyStroke('Z', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() + InputEvent.SHIFT_DOWN_MASK)); + else redo.setAccelerator(KeyStroke.getKeyStroke('Z', InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); + + mBar.add(proof); + + about.add(aboutLegup); + aboutLegup.addActionListener(l -> { + JOptionPane.showMessageDialog(null, "Version: 2.0.0"); + }); + + about.add(helpLegup); + helpLegup.addActionListener(l -> { + try { + java.awt.Desktop.getDesktop().browse(URI.create("https://github.com/jpoegs/Legup2.0")); + } catch (IOException e) { + LOGGER.error("Can't open web page"); + } + }); + + mBar.add(about); + + return mBar; + } + + public void promptPuzzle() { + GameBoardFacade facade = GameBoardFacade.getInstance(); + if (facade.getBoard() != null) { + if (noquit("Opening a new puzzle?")) // !noquit or noquit? + { + return; + } + } + + folderBrowser = new JFileChooser(); + + folderBrowser.showOpenDialog(this); + folderBrowser.setVisible(true); + folderBrowser.setCurrentDirectory(new java.io.File(".")); + folderBrowser.setDialogTitle("Select Directory"); + folderBrowser.setFileSelectionMode(JFileChooser.FILES_ONLY); + folderBrowser.setAcceptAllFileFilterUsed(true); + + String fileName = null; + File puzzleFile = folderBrowser.getSelectedFile(); + if (folderBrowser.getCurrentDirectory() != null && folderBrowser.getSelectedFile().getName() != null) { + fileName = puzzleFile.getAbsolutePath()+ File.separator; + puzzleFile = new File(fileName); + } + + if (puzzleFile != null && puzzleFile.exists()) { + try { + GameBoardFacade.getInstance().loadPuzzle(fileName); + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + frame.setTitle(puzzleName + " - " + puzzleFile.getName()); + } catch (InvalidFileFormatException e) { + LOGGER.error(e.getMessage()); + if (e.getMessage().contains("Proof Tree construction error: could not find rule by ID")) // TO DO: make error message not hardcoded + JOptionPane.showMessageDialog(null, "This file runs on an outdated version of Legup\nand is not compatible with the current version.", "Error", JOptionPane.ERROR_MESSAGE); + else + JOptionPane.showMessageDialog(null, "File does not exist or it cannot be read", "Error", JOptionPane.ERROR_MESSAGE); + } + } + } + + /** + * Saves a proof + */ + private void saveProof() { + Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); + if (puzzle == null) { + return; + } + + fileDialog.setMode(FileDialog.SAVE); + fileDialog.setTitle("Save Proof"); + String curFileName = GameBoardFacade.getInstance().getCurFileName(); + if (curFileName == null) { + fileDialog.setDirectory(LegupPreferences.getInstance().getUserPref(LegupPreferences.WORK_DIRECTORY)); + } else { + File curFile = new File(curFileName); + fileDialog.setDirectory(curFile.getParent()); + } + fileDialog.setVisible(true); + + String fileName = null; + if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { + fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); + } + + if (fileName != null) { + try { + PuzzleExporter exporter = puzzle.getExporter(); + if (exporter == null) { + throw new ExportFileException("Puzzle exporter null"); + } + exporter.exportPuzzle(fileName); + } catch (ExportFileException e) { + e.printStackTrace(); + } + } + } + + //ask to edu.rpi.legup.save current proof + public boolean noquit(String instr) { + int n = JOptionPane.showConfirmDialog(null, instr, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION); + return n != JOptionPane.YES_OPTION; + } + + /** + * Sets the main content for the edu.rpi.legup.user interface + */ + protected void setupContent() { +// JPanel consoleBox = new JPanel(new BorderLayout()); + JPanel treeBox = new JPanel(new BorderLayout()); + JPanel ruleBox = new JPanel(new BorderLayout()); + + RuleController ruleController = new RuleController(); + ruleFrame = new RuleFrame(ruleController); + ruleBox.add(ruleFrame, BorderLayout.WEST); + + treePanel = new TreePanel(); + + dynamicBoardView = new DynamicView(new ScrollView(new BoardController())); + TitledBorder titleBoard = BorderFactory.createTitledBorder("Board"); + titleBoard.setTitleJustification(TitledBorder.CENTER); + dynamicBoardView.setBorder(titleBoard); + + JPanel boardPanel = new JPanel(new BorderLayout()); + topHalfPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, ruleFrame, dynamicBoardView); + mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, topHalfPanel, treePanel); + topHalfPanel.setPreferredSize(new Dimension(600, 400)); + mainPanel.setPreferredSize(new Dimension(600, 600)); + + boardPanel.add(mainPanel); + boardBorder = BorderFactory.createTitledBorder("Board"); + boardBorder.setTitleJustification(TitledBorder.CENTER); + + ruleBox.add(boardPanel); + treeBox.add(ruleBox); + this.add(treeBox); +// consoleBox.add(treeBox); +// +// getContentPane().add(consoleBox); + +// JPopupPanel popupPanel = new JPopupPanel(); +// setGlassPane(popupPanel); +// popupPanel.setVisible(true); + + mainPanel.setDividerLocation(mainPanel.getMaximumDividerLocation() + 100); +// frame.pack(); + revalidate(); + } + + private void setupToolBar() { + setToolBarButtons(new JButton[ToolbarName.values().length]); + for (int i = 0; i < ToolbarName.values().length; i++) { + String toolBarName = ToolbarName.values()[i].toString(); + URL resourceLocation = ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/" + toolBarName + ".png"); + JButton button = new JButton(toolBarName, new ImageIcon(resourceLocation)); + button.setFocusPainted(false); + getToolBarButtons()[i] = button; + } + + toolBar = new JToolBar(); + toolBar.setFloatable(false); + toolBar.setRollover(true); + + for (int i = 0; i < getToolBarButtons().length; i++) { + for (int s = 0; s < TOOLBAR_SEPARATOR_BEFORE.length; s++) { + if (i == TOOLBAR_SEPARATOR_BEFORE[s]) { + toolBar.addSeparator(); + } + } + String toolBarName = ToolbarName.values()[i].toString(); + + toolBar.add(getToolBarButtons()[i]); + getToolBarButtons()[i].setToolTipText(toolBarName); + + getToolBarButtons()[i].setVerticalTextPosition(SwingConstants.BOTTOM); + getToolBarButtons()[i].setHorizontalTextPosition(SwingConstants.CENTER); + } + +// toolBarButtons[ToolbarName.OPEN_PUZZLE.ordinal()].addActionListener((ActionEvent e) -> promptPuzzle()); +// toolBarButtons[ToolbarName.SAVE.ordinal()].addActionListener((ActionEvent e) -> saveProof()); +// toolBarButtons[ToolbarName.UNDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().undo()); +// toolBarButtons[ToolbarName.REDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().redo()); + toolBarButtons[ToolbarName.HINT.ordinal()].addActionListener((ActionEvent e) -> { + }); + toolBarButtons[ToolbarName.CHECK.ordinal()].addActionListener((ActionEvent e) -> checkProof()); + toolBarButtons[ToolbarName.SUBMIT.ordinal()].addActionListener((ActionEvent e) -> { + }); + toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].addActionListener((ActionEvent e) -> { + }); + + toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].addActionListener((ActionEvent e) -> checkProofAll()); + +// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(false); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.HINT.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.SUBMIT.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].setEnabled(true); + + this.add(toolBar, BorderLayout.NORTH); + } + + /** + * Sets the toolbar buttons + * + * @param toolBarButtons toolbar buttons + */ + public void setToolBarButtons(JButton[] toolBarButtons) { + this.toolBarButtons = toolBarButtons; + } + + /** + * Gets the toolbar buttons + * + * @return toolbar buttons + */ + public JButton[] getToolBarButtons() { + return toolBarButtons; + } + + /** + * Checks the proof for correctness + */ + private void checkProof() { + GameBoardFacade facade = GameBoardFacade.getInstance(); + Tree tree = GameBoardFacade.getInstance().getTree(); + Board board = facade.getBoard(); + Board finalBoard = null; + boolean delayStatus = true; //board.evalDelayStatus(); + + repaintAll(); + + Puzzle puzzle = facade.getPuzzleModule(); + + if (puzzle.isPuzzleComplete()) { + // This is for submission which is not integrated yet + /*int confirm = JOptionPane.showConfirmDialog(null, "Congratulations! Your proof is correct. Would you like to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); + if (confirm == JOptionPane.YES_OPTION) { + Submission submission = new Submission(board); + submission.submit(); + }*/ + JOptionPane.showMessageDialog(null, "Congratulations! Your proof is correct."); + } else { + String message = "\nThe game board is not solved."; + JOptionPane.showMessageDialog(null, message, "Invalid proof.", JOptionPane.ERROR_MESSAGE); + } + } + + private void repaintAll() { + boardView.repaint(); + treePanel.repaint(); + } + + public void setPuzzleView(Puzzle puzzle) { + this.boardView = puzzle.getBoardView(); + + dynamicBoardView = new DynamicView(boardView); + this.topHalfPanel.setRightComponent(dynamicBoardView); + this.topHalfPanel.setVisible(true); + String boardType = boardView.getBoard().getClass().getSimpleName(); + boardType = boardType.substring(0, boardType.indexOf("Board")); + TitledBorder titleBoard = BorderFactory.createTitledBorder(boardType + " Board"); + titleBoard.setTitleJustification(TitledBorder.CENTER); + dynamicBoardView.setBorder(titleBoard); + + this.treePanel.getTreeView().resetView(); + this.treePanel.getTreeView().setTree(puzzle.getTree()); + + puzzle.addTreeListener(treePanel.getTreeView()); + puzzle.addBoardListener(puzzle.getBoardView()); + + ruleFrame.getBasicRulePanel().setRules(puzzle.getBasicRules()); + ruleFrame.getCasePanel().setRules(puzzle.getCaseRules()); + ruleFrame.getContradictionPanel().setRules(puzzle.getContradictionRules()); + + toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true); +// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(true); + + reloadGui(); + } + + public void reloadGui() { + repaintTree(); + } + + public void repaintTree() { + treePanel.repaintTreeView(GameBoardFacade.getInstance().getTree()); + } + + /** + * Checks the proof for all files + */ + private void checkProofAll() { + GameBoardFacade facade = GameBoardFacade.getInstance(); + + /* + * Select dir to grade; recursively grade sub-dirs using traverseDir() + * Selected dir must have sub-dirs for each student: + * GradeThis + * | + * | -> Student 1 + * | | + * | | -> Proofs + */ + folderBrowser = new JFileChooser(); + + folderBrowser.showOpenDialog(this); + folderBrowser.setVisible(true); + folderBrowser.setCurrentDirectory(new java.io.File(".")); + folderBrowser.setDialogTitle("Select Directory"); + folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + folderBrowser.setAcceptAllFileFilterUsed(false); + + File folder = folderBrowser.getSelectedFile(); + + // Write csv file (Path,File-Name,Puzzle-Type,Score,Solved?) + File resultFile = new File(folder.getAbsolutePath() + File.separator + "result.csv"); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) { + writer.append("Name,File Name,Puzzle Type,Score,Solved?\n"); + + // Go through student folders + for (final File folderEntry : Objects.requireNonNull(folder.listFiles(File::isDirectory))) { + // Write path + String path = folderEntry.getName(); + traverseDir(folderEntry, writer, path); + } + }catch (IOException ex){ + LOGGER.error(ex.getMessage()); + } + JOptionPane.showMessageDialog(null, "Batch grading complete."); + } + + private boolean basicCheckProof(int[][] origCells) { + return false; + } + + private void traverseDir(File folder, BufferedWriter writer, String path) throws IOException { + // Recursively traverse directory + GameBoardFacade facade = GameBoardFacade.getInstance(); + + // Folder is empty + if(Objects.requireNonNull(folder.listFiles()).length == 0) { + writer.append(path).append(",Empty folder,,Ungradeable\n"); + return; + } + + // Travese directory, recurse if sub-directory found + // If ungradeable, do not leave a score (0, 1) + for(final File f : Objects.requireNonNull(folder.listFiles())) { + // Recurse + if(f.isDirectory()) { + traverseDir(f, writer, path + "/" + f.getName()); + continue; + } + + // Set path name + writer.append(path).append(","); + + // Load puzzle, run checker + // If wrong file type, ungradeable + String fName = f.getName(); + String fPath = f.getAbsolutePath(); + File puzzleFile = new File(fPath); + if(puzzleFile.exists()) { + // Try to load file. If invalid, note in csv + try { + // Load puzzle, run checker + GameBoardFacade.getInstance().loadPuzzle(fPath); + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + frame.setTitle(puzzleName + " - " + puzzleFile.getName()); + facade = GameBoardFacade.getInstance(); + Puzzle puzzle = facade.getPuzzleModule(); + + // Write data + writer.append(fName).append(","); + writer.append(puzzle.getName()).append(","); + if (puzzle.isPuzzleComplete()) + writer.append("1,Solved\n"); + else + writer.append("0,Unsolved\n"); + } catch (InvalidFileFormatException e) { + writer.append(fName).append(",Invalid,,Ungradeable\n"); + } + } else { + LOGGER.debug("Failed to run sim"); + } + } + } + + public BoardView getBoardView() { + return boardView; + } + + public DynamicView getDynamicBoardView() { + return dynamicBoardView; + } + + public TreePanel getTreePanel() { + return treePanel; + } + + /** + * Called when a action is pushed onto the edu.rpi.legup.history stack + * + * @param command action to push onto the stack + */ + @Override + public void onPushChange(ICommand command) { + LOGGER.info("Pushing " + command.getClass().getSimpleName() + " to stack."); + undo.setEnabled(true); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(true); + redo.setEnabled(false); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); + frame.setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); + } + + /** + * Called when the history is cleared + */ + @Override + public void onClearHistory() { + undo.setEnabled(false); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); + redo.setEnabled(false); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + } + + /** + * Called when an action is redone + * + * @param isBottom true if there are no more actions to undo, false otherwise + * @param isTop true if there are no more changes to redo, false otherwise + */ + @Override + public void onRedo(boolean isBottom, boolean isTop) { + undo.setEnabled(!isBottom); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); + redo.setEnabled(!isTop); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); + if (isBottom) { + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); + frame.setTitle(puzzleName + " - " + puzzleFile.getName()); + } else { + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); + frame.setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); + } + } + + /** + * Called when an action is undone + * + * @param isBottom true if there are no more actions to undo, false otherwise + * @param isTop true if there are no more changes to redo, false otherwise + */ + @Override + public void onUndo(boolean isBottom, boolean isTop) { + undo.setEnabled(!isBottom); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); + redo.setEnabled(!isTop); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); + if (isBottom) { + frame.setTitle(puzzleName + " - " + puzzleFile.getName()); + } else { + frame.setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); + } + } + + /** + * Submits the proof file + */ + private void submit() { + GameBoardFacade facade = GameBoardFacade.getInstance(); + Board board = facade.getBoard(); + boolean delayStatus = true; //board.evalDelayStatus(); + repaintAll(); + + Puzzle pm = facade.getPuzzleModule(); + if (pm.isPuzzleComplete() && delayStatus) { + // 0 means yes, 1 means no (Java's fault...) + int confirm = JOptionPane.showConfirmDialog(null, "Are you sure you wish to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); + if (confirm == 0) { + Submission submission = new Submission(board); + submission.submit(); + } + } else { + JOptionPane.showConfirmDialog(null, "Your proof is incorrect! Are you sure you wish to submit?", "Proof Submission", JOptionPane.YES_NO_OPTION); + Submission submit = new Submission(board); + } + } + + private void directions() { + JOptionPane.showMessageDialog(null, "For every move you make, you must provide a rule for it (located in the Rules panel).\n" + "While working on the edu.rpi.legup.puzzle, you may click on the \"Check\" button to test your proof for correctness.", "Directions", JOptionPane.PLAIN_MESSAGE); + } + + public void errorEncountered(String error) { + JOptionPane.showMessageDialog(null, error); + } + + public void showStatus(String status, boolean error, int timer) { + // TODO: implement + } +} diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleCreatorView.java b/src/main/java/edu/rpi/legup/ui/PuzzleCreatorView.java deleted file mode 100644 index 3e5877890..000000000 --- a/src/main/java/edu/rpi/legup/ui/PuzzleCreatorView.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.rpi.legup.ui; - -import edu.rpi.legup.ui.boardview.BoardView; - -import javax.swing.*; - -public class PuzzleCreatorView extends JFrame { - - private BoardView boardView; - - public PuzzleCreatorView(BoardView boardView) { - this.boardView = boardView; - - setContentPane(new DynamicView(boardView)); - } - -} diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java new file mode 100644 index 000000000..92dd83df9 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java @@ -0,0 +1,283 @@ +package edu.rpi.legup.ui; + +import edu.rpi.legup.app.GameBoardFacade; +import edu.rpi.legup.controller.BoardController; +import edu.rpi.legup.controller.EditorElementController; +import edu.rpi.legup.controller.ElementController; +import edu.rpi.legup.history.ICommand; +import edu.rpi.legup.history.IHistoryListener; +import edu.rpi.legup.model.Puzzle; +import edu.rpi.legup.save.InvalidFileFormatException; +import edu.rpi.legup.ui.boardview.BoardView; +import edu.rpi.legup.ui.puzzleeditorui.elementsview.ElementFrame; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.io.File; +import java.net.URL; + +public class PuzzleEditorPanel extends LegupPanel implements IHistoryListener { + + private final static Logger LOGGER = LogManager.getLogger(PuzzleEditorPanel.class.getName()); + private JMenu[] menus; + private JMenuBar menuBar; + private JToolBar toolBar; + private JFrame frame; + private JButton[] buttons; + JSplitPane splitPanel; + private JButton[] toolBarButtons; + private JPanel elementPanel; + private DynamicView dynamicBoardView; + private BoardView boardView; + private TitledBorder boardBorder; + //private JSplitPane splitPanel, topHalfPanel; + private FileDialog fileDialog; + private JMenuItem undo, redo; + private ElementFrame elementFrame; + private JPanel treePanel; + private LegupUI legupUI; + final static int[] TOOLBAR_SEPARATOR_BEFORE = {2, 4, 8}; + + public PuzzleEditorPanel(FileDialog fileDialog, JFrame frame, LegupUI legupUI) { + this.fileDialog = fileDialog; + this.frame = frame; + this.legupUI = legupUI; + setLayout(new BorderLayout()); + } + + protected void setupContent() { + JSplitPane splitPanel; + JPanel elementBox = new JPanel(new BorderLayout()); + + EditorElementController elementController = new EditorElementController(); + elementFrame = new ElementFrame(elementController); + elementBox.add(elementFrame, BorderLayout.WEST); + + dynamicBoardView = new DynamicView(new ScrollView(new BoardController())); + TitledBorder titleBoard = BorderFactory.createTitledBorder("Board"); + titleBoard.setTitleJustification(TitledBorder.CENTER); + dynamicBoardView.setBorder(titleBoard); + + JPanel boardPanel = new JPanel(new BorderLayout()); + splitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, elementFrame, dynamicBoardView); + splitPanel.setPreferredSize(new Dimension(600, 400)); + + boardPanel.add(splitPanel); + boardBorder = BorderFactory.createTitledBorder("Board"); + boardBorder.setTitleJustification(TitledBorder.CENTER); + + elementBox.add(boardPanel); + this.add(elementBox); + + splitPanel.setDividerLocation(splitPanel.getMaximumDividerLocation()+100); + this.splitPanel = splitPanel; + revalidate(); + } + + public void setMenuBar() { + String os = LegupUI.getOS(); + menuBar = new JMenuBar(); + menus = new JMenu[3]; + + // create menus + + // FILE + menus[0] = new JMenu("File"); + // file>new + JMenuItem newPuzzle = new JMenuItem("New"); + newPuzzle.addActionListener((ActionEvent) -> promptPuzzle()); + if(os.equals("mac")) newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK)); + // file>save + JMenuItem savePuzzle = new JMenuItem("Save"); + JMenuItem exit = new JMenuItem("Exit"); + exit.addActionListener((ActionEvent) -> this.legupUI.displayPanel(0)); + if (os.equals("mac")) + exit.setAccelerator(KeyStroke.getKeyStroke('Q', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + else + exit.setAccelerator(KeyStroke.getKeyStroke('Q', InputEvent.CTRL_DOWN_MASK)); + menus[0].add(newPuzzle); + menus[0].add(savePuzzle); + menus[0].add(exit); + + // EDIT + menus[1] = new JMenu("Edit"); + // edit>undo + undo = new JMenuItem("Undo"); + // edit>redo + redo = new JMenuItem("Redo"); + + menus[1].add(undo); + menus[1].add(redo); + + // HELP + menus[2] = new JMenu("Help"); + + // add menus to menubar + for (JMenu menu : menus) { + menuBar.add(menu); + } + frame.setJMenuBar(menuBar); + } + + @Override + public void makeVisible() { + this.removeAll(); + + setupToolBar(); + setupContent(); + setMenuBar(); + } + + private void setupToolBar() { + setToolBarButtons(new JButton[ToolbarName.values().length]); + for (int i = 0; i < ToolbarName.values().length; i++) { + String toolBarName = ToolbarName.values()[i].toString(); + URL resourceLocation = ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/" + toolBarName + ".png"); + JButton button = new JButton(toolBarName, new ImageIcon(resourceLocation)); + button.setFocusPainted(false); + getToolBarButtons()[i] = button; + } + toolBar = new JToolBar(); + toolBar.setFloatable(false); + toolBar.setRollover(true); + + for (int i = 0; i < getToolBarButtons().length; i++) { + for (int s = 0; s < TOOLBAR_SEPARATOR_BEFORE.length; s++) { + if (i == TOOLBAR_SEPARATOR_BEFORE[s]) { + toolBar.addSeparator(); + } + } + String toolBarName = ToolbarName.values()[i].toString(); + + toolBar.add(getToolBarButtons()[i]); + getToolBarButtons()[i].setToolTipText(toolBarName); + + getToolBarButtons()[i].setVerticalTextPosition(SwingConstants.BOTTOM); + getToolBarButtons()[i].setHorizontalTextPosition(SwingConstants.CENTER); + } + +// toolBarButtons[ToolbarName.OPEN_PUZZLE.ordinal()].addActionListener((ActionEvent e) -> promptPuzzle()); +// toolBarButtons[ToolbarName.SAVE.ordinal()].addActionListener((ActionEvent e) -> saveProof()); +// toolBarButtons[ToolbarName.UNDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().undo()); +// toolBarButtons[ToolbarName.REDO.ordinal()].addActionListener((ActionEvent e) -> GameBoardFacade.getInstance().getHistory().redo()); + toolBarButtons[ToolbarName.HINT.ordinal()].addActionListener((ActionEvent e) -> { + }); + toolBarButtons[ToolbarName.SUBMIT.ordinal()].addActionListener((ActionEvent e) -> { + }); + toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].addActionListener((ActionEvent e) -> { + }); + +// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(false); +// toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); +// toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.HINT.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.SUBMIT.ordinal()].setEnabled(false); + toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].setEnabled(false); + + this.add(toolBar, BorderLayout.NORTH); + } + public void loadPuzzleFromHome(String game, int rows, int columns) throws IllegalArgumentException { + GameBoardFacade facade = GameBoardFacade.getInstance(); + try { + facade.loadPuzzle(game, rows, columns); + } + catch (IllegalArgumentException exception) + { + throw new IllegalArgumentException(exception.getMessage()); + } + catch (RuntimeException e){ + LOGGER.error(e.getMessage()); + } + } + public void promptPuzzle() { + GameBoardFacade facade = GameBoardFacade.getInstance(); + if (facade.getBoard() != null) { + if (noQuit("Opening a new puzzle to edit?")) // !noquit or noquit? + { + return; + } + } + + fileDialog.setMode(FileDialog.LOAD); + fileDialog.setTitle("Select Puzzle"); + fileDialog.setVisible(true); + String fileName = null; + File puzzleFile = null; + if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { + fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); + puzzleFile = new File(fileName); + } + + if (puzzleFile != null && puzzleFile.exists()) { + try { + GameBoardFacade.getInstance().loadPuzzle(fileName); + String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); + frame.setTitle(puzzleName + " - " + puzzleFile.getName()); + } catch (InvalidFileFormatException e) { + LOGGER.error(e.getMessage()); + } + } + } + public boolean noQuit(String instr) { + int n = JOptionPane.showConfirmDialog(null, instr, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION); + return n != JOptionPane.YES_OPTION; + } + + @Override + public void onPushChange(ICommand command) { + + } + + @Override + public void onUndo(boolean isBottom, boolean isTop) { + + } + + @Override + public void onRedo(boolean isBottom, boolean isTop) { + + } + + @Override + public void onClearHistory() { + + } + + public JButton[] getToolBarButtons() { + return toolBarButtons; + } + public void setToolBarButtons(JButton[] toolBarButtons) { + this.toolBarButtons = toolBarButtons; + } + + private void repaintAll() { + boardView.repaint(); + } + + public void setPuzzleView(Puzzle puzzle) { + this.boardView = puzzle.getBoardView(); + dynamicBoardView = new DynamicView(boardView); + + this.splitPanel.setRightComponent(dynamicBoardView); + this.splitPanel.setVisible(true); + + TitledBorder titleBoard = BorderFactory.createTitledBorder(boardView.getClass().getSimpleName()); + titleBoard.setTitleJustification(TitledBorder.CENTER); + dynamicBoardView.setBorder(titleBoard); + + puzzle.addBoardListener(puzzle.getBoardView()); + + elementFrame.getNonPlaceableElementPanel().setElements(puzzle.getNonPlaceableElements()); + elementFrame.getPlaceableElementPanel().setElements(puzzle.getPlaceableElements()); + + toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true); +// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(true); + } + +} diff --git a/src/main/java/edu/rpi/legup/ui/boardview/GridBoardView.java b/src/main/java/edu/rpi/legup/ui/boardview/GridBoardView.java index 6b352370f..e851d14d7 100644 --- a/src/main/java/edu/rpi/legup/ui/boardview/GridBoardView.java +++ b/src/main/java/edu/rpi/legup/ui/boardview/GridBoardView.java @@ -5,7 +5,6 @@ import java.awt.Color; import java.awt.Dimension; -import java.awt.Point; public class GridBoardView extends BoardView { protected Dimension gridSize; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/BasicRulePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/BasicRulePanel.java similarity index 93% rename from src/main/java/edu/rpi/legup/ui/rulesview/BasicRulePanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/BasicRulePanel.java index 6307b81d5..4e9bbd62a 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/BasicRulePanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/BasicRulePanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/CaseRulePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRulePanel.java similarity index 91% rename from src/main/java/edu/rpi/legup/ui/rulesview/CaseRulePanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRulePanel.java index 534825dc7..5f22ac62c 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/CaseRulePanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRulePanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import javax.swing.ImageIcon; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/CaseRuleSelectionView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRuleSelectionView.java similarity index 90% rename from src/main/java/edu/rpi/legup/ui/rulesview/CaseRuleSelectionView.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRuleSelectionView.java index eda8e0cb9..276583a99 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/CaseRuleSelectionView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/CaseRuleSelectionView.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import edu.rpi.legup.ui.WrapLayout; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/ContradictionRulePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/ContradictionRulePanel.java similarity index 91% rename from src/main/java/edu/rpi/legup/ui/rulesview/ContradictionRulePanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/ContradictionRulePanel.java index 4b81b6ade..908ffc49b 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/ContradictionRulePanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/ContradictionRulePanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import javax.swing.*; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/RuleButton.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java similarity index 93% rename from src/main/java/edu/rpi/legup/ui/rulesview/RuleButton.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java index ca898a25c..12cae7de1 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/RuleButton.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import edu.rpi.legup.model.rules.Rule; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/RuleFrame.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java similarity index 99% rename from src/main/java/edu/rpi/legup/ui/rulesview/RuleFrame.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java index fd7bb869e..cfe3ba3b4 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/RuleFrame.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import edu.rpi.legup.controller.RuleController; import edu.rpi.legup.model.Puzzle; diff --git a/src/main/java/edu/rpi/legup/ui/rulesview/RulePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java similarity index 98% rename from src/main/java/edu/rpi/legup/ui/rulesview/RulePanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java index de01f3916..c6bc2ee0a 100644 --- a/src/main/java/edu/rpi/legup/ui/rulesview/RulePanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.rulesview; +package edu.rpi.legup.ui.proofeditorui.rulesview; import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.ui.WrapLayout; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeElementView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeElementView.java similarity index 98% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeElementView.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeElementView.java index 3c46c5241..676992654 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeElementView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeElementView.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import edu.rpi.legup.model.tree.TreeElement; import edu.rpi.legup.model.tree.TreeElementType; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeNodeView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeNodeView.java similarity index 99% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeNodeView.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeNodeView.java index 55d586f4d..f60ffe300 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeNodeView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeNodeView.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import edu.rpi.legup.model.rules.RuleType; import edu.rpi.legup.model.tree.TreeElementType; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreePanel.java similarity index 96% rename from src/main/java/edu/rpi/legup/ui/treeview/TreePanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreePanel.java index 31c8de096..306cffec8 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreePanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreePanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.controller.TreeController; @@ -7,7 +7,6 @@ import edu.rpi.legup.history.ICommand; import edu.rpi.legup.history.MergeCommand; import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.Tree; import edu.rpi.legup.ui.DynamicView; import edu.rpi.legup.ui.LegupUI; @@ -33,8 +32,8 @@ public class TreePanel extends JPanel { private JLabel status; - public TreePanel(LegupUI legupUI) { - this.legupUI = legupUI; + public TreePanel(/*LegupUI legupUI*/) { + //this.legupUI = legupUI; main = new JPanel(); diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarButton.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarButton.java similarity index 87% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarButton.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarButton.java index ab63bab81..85c1c73c8 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarButton.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarButton.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import javax.swing.*; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarName.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarName.java similarity index 60% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarName.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarName.java index 309fa3048..dd8a37c15 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolBarName.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolBarName.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; public enum TreeToolBarName { ADD_CHILD, DEL_CHILD, MERGE, COLLAPSE diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolbarPanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolbarPanel.java similarity index 97% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeToolbarPanel.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolbarPanel.java index 50b31d74c..97ea419e6 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeToolbarPanel.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeToolbarPanel.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import javax.swing.*; import java.awt.*; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeTransitionView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeTransitionView.java similarity index 99% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeTransitionView.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeTransitionView.java index a71f92800..3f1f59ba5 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeTransitionView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeTransitionView.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import edu.rpi.legup.model.tree.TreeElementType; import edu.rpi.legup.model.tree.TreeTransition; diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java similarity index 99% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeView.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java index 01ec07d32..79367216a 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.controller.TreeController; @@ -21,8 +21,8 @@ import static edu.rpi.legup.model.tree.TreeElementType.NODE; import static edu.rpi.legup.model.tree.TreeElementType.TRANSITION; -import static edu.rpi.legup.ui.treeview.TreeNodeView.DIAMETER; -import static edu.rpi.legup.ui.treeview.TreeNodeView.RADIUS; +import static edu.rpi.legup.ui.proofeditorui.treeview.TreeNodeView.DIAMETER; +import static edu.rpi.legup.ui.proofeditorui.treeview.TreeNodeView.RADIUS; public class TreeView extends ScrollView implements ITreeListener { private final static Logger LOGGER = LogManager.getLogger(TreeView.class.getName()); diff --git a/src/main/java/edu/rpi/legup/ui/treeview/TreeViewSelection.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeViewSelection.java similarity index 98% rename from src/main/java/edu/rpi/legup/ui/treeview/TreeViewSelection.java rename to src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeViewSelection.java index 0c76aa5e0..575d19f19 100644 --- a/src/main/java/edu/rpi/legup/ui/treeview/TreeViewSelection.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeViewSelection.java @@ -1,4 +1,4 @@ -package edu.rpi.legup.ui.treeview; +package edu.rpi.legup.ui.proofeditorui.treeview; import java.awt.*; import java.util.List; diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java new file mode 100644 index 000000000..a7fe8bf7c --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java @@ -0,0 +1,23 @@ +package edu.rpi.legup.ui.puzzleeditorui.elementsview; + +import edu.rpi.legup.model.elements.Element; +import edu.rpi.legup.model.rules.Rule; + +import javax.swing.*; + +public class ElementButton extends JButton { + + private Element element; + ElementButton(Element e) { + super(e.getImageIcon()); + this.element = e; + } + + public Element getElement() { + return element; + } + + public void setElement(Element e) { + this.element = e; + } +} diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java new file mode 100644 index 000000000..ebb0e9ca4 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java @@ -0,0 +1,73 @@ +package edu.rpi.legup.ui.puzzleeditorui.elementsview; + +import edu.rpi.legup.controller.EditorElementController; +import edu.rpi.legup.model.Puzzle; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +public class ElementFrame extends JPanel { + private static final String checkBox = " \u2714 "; + private static final String xBox = " \u2718 "; + private static final String htmlHead = ""; + private static final String htmlTail = ""; + + private PlaceableElementPanel placeableElementPanel; + private NonPlaceableElementPanel nonPlaceableElementPanel; + private JTabbedPane tabbedPane; + private JLabel status; + private ButtonGroup buttonGroup; + + private EditorElementController controller; + + public ElementFrame(EditorElementController controller) { + this.controller = controller; + + this.tabbedPane = new JTabbedPane(); + this.status = new JLabel("", SwingConstants.CENTER); + this.buttonGroup = new ButtonGroup(); + + placeableElementPanel = new PlaceableElementPanel(this); + tabbedPane.addTab(placeableElementPanel.getName(), placeableElementPanel.getIcon(), new JScrollPane(placeableElementPanel), placeableElementPanel.getToolTip()); + + nonPlaceableElementPanel = new NonPlaceableElementPanel(this); + tabbedPane.addTab(nonPlaceableElementPanel.getName(), nonPlaceableElementPanel.getIcon(), new JScrollPane(nonPlaceableElementPanel), nonPlaceableElementPanel.getToolTip()); + + setLayout(new BorderLayout()); + setMinimumSize(new Dimension(250, 256)); + setPreferredSize(new Dimension(330, 256)); + + add(tabbedPane); + add(status, BorderLayout.SOUTH); + + TitledBorder title = BorderFactory.createTitledBorder("Elements"); + title.setTitleJustification(TitledBorder.CENTER); + setBorder(title); + } + + public ButtonGroup getButtonGroup() { + return buttonGroup; + } + + public void resetSize() { + int buttonWidth = ((ElementPanel) tabbedPane.getSelectedComponent()).getElementButtons()[0].getWidth(); + this.setMinimumSize(new Dimension(2 * buttonWidth + 64, this.getHeight())); + } + + public void setElements(Puzzle puzzle) { + placeableElementPanel.setElements(puzzle.getPlaceableElements()); + nonPlaceableElementPanel.setElements(puzzle.getNonPlaceableElements()); + } + + public EditorElementController getController() { + return controller; + } + + public JTabbedPane getTabbedPane() { + return tabbedPane; + } + + public NonPlaceableElementPanel getNonPlaceableElementPanel() { return nonPlaceableElementPanel; } + public PlaceableElementPanel getPlaceableElementPanel() { return placeableElementPanel; } +} diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementPanel.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementPanel.java new file mode 100644 index 000000000..4c2bebd54 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementPanel.java @@ -0,0 +1,82 @@ +package edu.rpi.legup.ui.puzzleeditorui.elementsview; + +import edu.rpi.legup.model.rules.Rule; +import edu.rpi.legup.ui.WrapLayout; +import edu.rpi.legup.model.elements.Element; +import edu.rpi.legup.ui.proofeditorui.rulesview.RuleButton; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +public abstract class ElementPanel extends JPanel { + protected ImageIcon icon; + protected String name; + protected String toolTip; + protected ElementButton[] elementButtons; + protected ElementFrame elementFrame; + protected List elements; + + public ElementPanel(ElementFrame eFrame) { + this.elementFrame = eFrame; + this.elements = new ArrayList<>(); + setLayout(new WrapLayout()); + } + public void setElements(List elements) { + this.elements = elements; + clearButtons(); + + elementButtons = new ElementButton[elements.size()]; + + for (int i = 0; i < elements.size(); i++) { + Element element = elements.get(i); + elementButtons[i] = new ElementButton(element); + elementFrame.getButtonGroup().add(elementButtons[i]); + + elementButtons[i].setToolTipText(element.getElementName() + ": " + element.getDescription()); + elementButtons[i].addActionListener(elementFrame.getController()); + add(elementButtons[i]); + } + revalidate(); + } + + protected void clearButtons() { + if (elementButtons != null) { + removeAll(); + for (int x = 0; x < elementButtons.length; ++x) { + elementButtons[x].removeActionListener(elementFrame.getController()); + } + } + } + + public ElementButton[] getElementButtons() { + return elementButtons; + } + + public ImageIcon getIcon() { + return icon; + } + + public void setIcon(ImageIcon icon) { + this.icon = icon; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + public String getToolTip() { + return toolTip; + } + + public void setToolTip(String toolTip) { + this.toolTip = toolTip; + } +} + diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/NonPlaceableElementPanel.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/NonPlaceableElementPanel.java new file mode 100644 index 000000000..6704d1aa2 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/NonPlaceableElementPanel.java @@ -0,0 +1,12 @@ +package edu.rpi.legup.ui.puzzleeditorui.elementsview; + +import javax.swing.*; + +public class NonPlaceableElementPanel extends ElementPanel{ + public NonPlaceableElementPanel(ElementFrame elementFrame) { + super(elementFrame); + this.icon = new ImageIcon(ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/Basic Rules.gif")); + this.name = "Non-Placeable Elements"; + this.toolTip = "Non-Placeable Elements"; + } +} diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/PlaceableElementPanel.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/PlaceableElementPanel.java new file mode 100644 index 000000000..2021d43cc --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/PlaceableElementPanel.java @@ -0,0 +1,12 @@ +package edu.rpi.legup.ui.puzzleeditorui.elementsview; + +import javax.swing.*; + +public class PlaceableElementPanel extends ElementPanel{ + public PlaceableElementPanel(ElementFrame elementFrame) { + super(elementFrame); + this.icon = new ImageIcon(ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/Basic Rules.gif")); + this.name = "Placeable Elements"; + this.toolTip = "Placeable Elements"; + } +} diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/resizeview/ResizePanel.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/resizeview/ResizePanel.java new file mode 100644 index 000000000..7cb7856e7 --- /dev/null +++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/resizeview/ResizePanel.java @@ -0,0 +1,4 @@ +package edu.rpi.legup.ui.puzzleeditorui.resizeview; + +public class ResizePanel { +} diff --git a/src/main/resources/edu/rpi/legup/homepanel/edit.png b/src/main/resources/edu/rpi/legup/homepanel/edit.png new file mode 100644 index 000000000..af7cb9d4a Binary files /dev/null and b/src/main/resources/edu/rpi/legup/homepanel/edit.png differ diff --git a/src/main/resources/edu/rpi/legup/homepanel/newpuzzle.png b/src/main/resources/edu/rpi/legup/homepanel/newpuzzle.png new file mode 100644 index 000000000..24ebfd346 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/homepanel/newpuzzle.png differ diff --git a/src/main/resources/edu/rpi/legup/homepanel/openproof.png b/src/main/resources/edu/rpi/legup/homepanel/openproof.png new file mode 100644 index 000000000..69dbdabcc Binary files /dev/null and b/src/main/resources/edu/rpi/legup/homepanel/openproof.png differ diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index 9a40395f1..5e685d554 100644 --- a/src/main/resources/edu/rpi/legup/legup/config +++ b/src/main/resources/edu/rpi/legup/legup/config @@ -1,14 +1,43 @@ - + - - - - - - - - - - + + + + + + + + + + \ No newline at end of file