/** * Copyright (C) 2013 Tokanagrammar Team * * This is a jigsaw-like puzzle game, * except each piece is token from a source file, * and the 'complete picture' is the program. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package edu.umb.cs.gui; import edu.umb.cs.source.SourceFile; import edu.umb.cs.source.SourceToken; import edu.umb.cs.source.SourceTokenKind; import edu.umb.cs.source.std.SourceTokenBase; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.image.ImageView; import javafx.scene.input.DragEvent; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; public class GameBoard { private static Pane legalDragZone; private static ObservableList<Node> ldzChildren; private static final GameBoard gameBoard = new GameBoard(); private GameBoard(){} /** * There can only be one instance of the LegalDragZone * at any time. This uses the Singleton pattern to ensure this. * @return an instance of the LegalDragZone */ public static GameBoard getInstance(){ legalDragZone = Controller.getLegalDragZone(); ldzChildren = legalDragZone.getChildren(); return gameBoard; } //-------------------------------------------------------------------------- //TOKEN BOARD static final int TOKENBOARD_OFFSET = 5; static final int TOKENBOARD_WIDTH = 510; static final int TOKENBOARD_HEIGHT = 427; static final int TOKENBOARD_BUFFERSIZE = 1; static final int TOKENBOARD_ROWHEIGHT = 30; private static VBox lhsLineContainer = new VBox(); private static List<Node> lhsLines = lhsLineContainer.getChildren(); private static List<LHSIconizedToken> tokenBoardItokens; /**Places the tokens in the tokenBoard by calling settleTokenBoard**/ public void initTokenBoard(SourceFile src){ final ScrollPane scrollPane = new ScrollPane(); scrollPane.setMinWidth(TOKENBOARD_WIDTH); scrollPane.setMinHeight(TOKENBOARD_HEIGHT); scrollPane.setMaxWidth(TOKENBOARD_WIDTH); scrollPane.setMaxHeight(TOKENBOARD_HEIGHT); scrollPane.setStyle("-fx-background-color: transparent;"); ldzChildren.add(scrollPane); lhsLineContainer.setPadding(new Insets(0, 5, 0, 5)); scrollPane.setContent(lhsLineContainer); tokenBoardItokens = settleTokenBoard(src); } public void refreshTokenBoard() { } public void resetTokenBoard(){ lhsLines.removeAll(lhsLines); tokenBoardItokens.removeAll(tokenBoardItokens); RHSTokenIconizer.resetIndex(); LHSTokenIconizer.resetIndex(); } /** * Properly formats the LHS. * @param tokens */ private List<LHSIconizedToken> settleTokenBoard(SourceFile src) { List<LHSIconizedToken> ret = new ArrayList<>(src.tokenCount()); HBox line = new HBox(); Label lineNumber = new Label(1 + ""); int lineCount = src.lineCount(); for (int lineIndex = 0; lineIndex < lineCount; ++lineIndex) { line.setMinHeight(30); lineNumber = new Label(lineIndex + 1 + ((lineIndex + 1 + "").length() == 1 ? " " : " ")); lineNumber.setStyle("-fx-fill:black; -fx-padding: 0, 0, 0, 0;"); line.getChildren().add(lineNumber); for (SourceToken curToken : src.getTokens(lineIndex)) { final LHSIconizedToken iconizedCurTok = LHSTokenIconizer.iconizeToken(curToken); ret.add(iconizedCurTok); ImageView imgView = iconizedCurTok.getImgView(); line.getChildren().add(imgView); } lhsLines.add(line); line = new HBox(); } return ret; } //-------------------------------------------------------------------------- //TOKEN BAY static final int TOKENBAY_WIDTH = 233; static final int TOKENBAY_HEIGHT = 427; static final int TOKENBAY_BUFFERSIZE = 5; static final int TOKENBAY_ROWHEIGHT = 25; static final int SCROLL_BAR_PADDING = 10; private static List<RHSIconizedToken> tokenBayItokens; private static int tokenBayCurrentRow; private static int tokenBayStartPosition = TOKENBAY_BUFFERSIZE; private static Pane tokenBay = new Pane(); private static ObservableList<Node> tokenBayChildren; /**Places the tokens in the tokenBay by calling settleTokenBay**/ public void initTokenBay(List<RHSIconizedToken> iTokens){ tokenBayItokens = iTokens; final ScrollPane scrollPane = new ScrollPane(); scrollPane.setStyle("-fx-background-color: transparent;"); ldzChildren.add(scrollPane); scrollPane.setContent(tokenBay); scrollPane.setLayoutX(545); scrollPane.setLayoutY(0); scrollPane.setMinWidth(230); scrollPane.setMinHeight(421); scrollPane.setMaxWidth(230); scrollPane.setMaxHeight(421); tokenBay.setMinHeight(421); tokenBay.setMinWidth(225); tokenBay.setMaxWidth(225); tokenBay.setOnDragOver(new EventHandler<DragEvent>(){ @Override public void handle(DragEvent event) { Dragboard db = event.getDragboard(); if (db.hasString()) event.acceptTransferModes(TransferMode.ANY); } }); tokenBay.setOnDragDropped(new EventHandler<DragEvent>() { public void handle(DragEvent event) { Dragboard db = event.getDragboard(); boolean success = false; if (db.hasString()) { String dragBoardContent = db.getString(); String delim = "[:::]+"; String[] strs = dragBoardContent.split(delim); SourceToken sourceToken = new SourceTokenBase(strs[1], // image SourceTokenKind.valueOf(strs[0])); // kind String index = strs[2]; // index System.err.println("kind: " + strs[0]); System.err.println("index: " + strs[2]); Integer intIndex = 0; RHSIconizedToken replacementRHSiToken = RHSTokenIconizer.createSingleIconizedToken(sourceToken, intIndex); //Replace the blank spot with the iToken. //getTokenBayItokens().remove((int)intIndex); getTokenBayItokens().add(intIndex, replacementRHSiToken); ImageView rImgView = replacementRHSiToken.getImgView(); rImgView.setLayoutX(event.getX()); rImgView.setLayoutY(event.getY()); tokenBayChildren.add(replacementRHSiToken.getImgView()); System.err.println(tokenBayChildren.size()); success = true; } event.setDropCompleted(success); event.consume(); } }); settleTokenBay(iTokens); } public void resetTokenBay(){ tokenBayCurrentRow = 0; tokenBayStartPosition = TOKENBAY_BUFFERSIZE; tokenBayChildren.removeAll(tokenBayChildren); tokenBayItokens.removeAll(tokenBayItokens); } public boolean removeRHSiToken(RHSIconizedToken iToken){ return tokenBayItokens.remove(iToken); } /** * Uses a circular buffer technique to place all the tokens removed * from the original source on the RHS in a "best fit" manner. * @param tokens */ private void settleTokenBay(List<RHSIconizedToken> rhsTokens){ LinkedList<RHSIconizedToken> tooLargeForLine = new LinkedList<RHSIconizedToken>(); tokenBayChildren = tokenBay.getChildren(); for(int i=0; i < rhsTokens.size(); i++){ final RHSIconizedToken curToken = rhsTokens.get(i); final double tokenWidth = curToken.getImage().getWidth(); if((TOKENBAY_WIDTH) < ( tokenBayStartPosition + tokenWidth + TOKENBAY_BUFFERSIZE + SCROLL_BAR_PADDING) ) tooLargeForLine.add(curToken); else{ ImageView imgView = curToken.getImgView(); imgView.setLayoutX(tokenBayStartPosition); imgView.setLayoutY(tokenBayCurrentRow * TOKENBAY_ROWHEIGHT); //This is for visual dragging, which hopefully gets fixed soon! //TODO re-implement visual dragging. curToken.setStartX(imgView.getLayoutX()); curToken.setStartY(imgView.getLayoutY()); tokenBayChildren.add(imgView); tokenBayStartPosition += (tokenWidth + TOKENBAY_BUFFERSIZE); } } if(!tooLargeForLine.isEmpty()){ tokenBayStartPosition = TOKENBAY_BUFFERSIZE; tokenBayCurrentRow++; settleTokenBay(tooLargeForLine); } } //-------------------------------------------------------------------------- //GETTERS / SETTERS public Pane getLDZpane(){ return legalDragZone; } public List<LHSIconizedToken> getTokenBoardItokens(){ return tokenBoardItokens; } public List<RHSIconizedToken> getTokenBayItokens(){ return tokenBayItokens; } /** * If all the tokens on the RHS have been removed, we have to turn on * the compile button. This is used to test that case. * @return */ public boolean isRHSempty(){ String compileMessage = ""; for(RHSIconizedToken rhsItoken: getTokenBayItokens()) if (rhsItoken.getSourceToken().kind() != SourceTokenKind.EMPTY || getTokenBayItokens() == null) return false; OutputPanel.getInstance().compilerMessage(compileMessage + ""); return true; } private LinkedList<String> parseDbContent(String dbContent){ return null; } }