/* * Copyright 2012, 2013 Evan Flynn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.foobar.minesweeper; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Parent; import javafx.scene.control.ButtonBuilder; import javafx.scene.control.Label; import javafx.scene.control.LabelBuilder; import javafx.scene.image.Image; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBoxBuilder; import javafx.scene.layout.PaneBuilder; import org.foobar.minesweeper.model.Minefield; import org.foobar.minesweeper.model.Minefield.FieldHandler; import org.foobar.minesweeper.model.Minefield.State; import org.foobar.minesweeper.model.Square; import org.foobar.minesweeper.model.Squares; public final class MinesweeperPane implements HasParent { private final Parent root; private final Label status; private final int rows; private final int columns; private final Minefield field; private final FieldCanvas canvas; private final Minesweeper appController; public MinesweeperPane(MinesweeperPane pane) { this(pane.field, pane.appController); } public MinesweeperPane(Minefield field, final Minesweeper appController) { this.field = field; this.appController = appController; rows = field.getRowCount(); columns = field.getColumnCount(); canvas = new FieldCanvas(); canvas.setLayoutX(14); canvas.setLayoutY(49.0); canvas.setWidth(240); canvas.setHeight(240); canvas.setOnMouseClicked(this::onCanvasClicked); canvas.setOnMousePressed(this::onCanvasPressed); root = PaneBuilder.create() .style("-fx-border-color: black;" + "-fx-border-width: 1;" + "-fx-border-radius: 6;" + "-fx-padding: 6;" + "-fx-background-color: white;") .prefHeight(308) .prefWidth(268) .children( HBoxBuilder.create() .layoutX(14) .layoutY(14) .spacing(10) .children( ButtonBuilder.create() .text("_New Game") .onAction(event -> onNewGame()).build(), ButtonBuilder.create() .text("C_lone") .onAction(event -> appController.onClone(MinesweeperPane.this)).build(), ButtonBuilder.create() .text("_Close") .onAction(event -> appController.onClone(MinesweeperPane.this)).build() ).build(), canvas, status = LabelBuilder.create() .text("") .layoutX(14) .layoutY(290).build() ).build(); Draggable.makeDraggable(root); field.addFieldHandler(new FieldHandler() { @Override public void updateSquare(Square square) { drawSquare(square); } @Override public void updateBoard() { drawBoard(); } @Override public void changeState(State state) { updateText(state); } }); } public Parent asParent() { return root; } private void onNewGame() { field.reset(); } private void onCanvasClicked(MouseEvent event) { Square square = findSquare(event); int clicks = event.getClickCount(); MouseButton button = event.getButton(); // FIXME: square doesn't always redraw after mouse click if (button == MouseButton.MIDDLE || (clicks == 2 && button == MouseButton.PRIMARY)) { square.revealNearby(); } else if (clicks == 1 && button == MouseButton.PRIMARY) { canvas.clearSelection(); square.reveal(); } } private void onCanvasPressed(MouseEvent event) { Square square = findSquare(event); int row = square.getRow(); int column = square.getColumn(); if (event.isSecondaryButtonDown()) { square.toggleFlag(); } else if (event.isPrimaryButtonDown() && square.isRevealable()) { canvas.setSelection(row, column); } } private void drawSquare(Square square) { Image image = square.getType() == Squares.EXPOSED ? Tiles.getDigit(square .getMineCount()) : Tiles.getImage(square.getType()); canvas.drawImage(square.getRow(), square.getColumn(), image); } private void updateText(Minefield.State state) { String text; switch(state) { case LOST: text = "You lost! Click New Game to try again."; break; case WON: text = "Congratulations, you won!"; break; default: text = ""; } status.setText(text); } private void drawBoard() { for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { drawSquare(field.getSquare(row, column)); } } } private Square findSquare(MouseEvent event) { return field.getSquare(canvas.scaleRow(event.getY()), canvas.scaleColumn(event.getX())); } }