/******************************************************************************* * Solitaire * * Copyright (C) 2016 by Martin P. Robillard * * See: https://github.com/prmr/Solitaire * * 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 * (at your option) 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 ca.mcgill.cs.stg.solitaire.gui; import ca.mcgill.cs.stg.solitaire.cards.CardImages; import ca.mcgill.cs.stg.solitaire.model.GameModel; import ca.mcgill.cs.stg.solitaire.model.GameModelListener; import javafx.event.EventHandler; import javafx.geometry.VPos; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.control.Button; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.TextAlignment; /** * Component that shows the deck and allows clicking * it to draw cards. Listens to game model state changes * and updates itself to disappear if it is empty. */ class DeckView extends HBox implements GameModelListener { private static final String BUTTON_STYLE_NORMAL = "-fx-background-color: transparent; -fx-padding: 5, 5, 5, 5;"; private static final String BUTTON_STYLE_PRESSED = "-fx-background-color: transparent; -fx-padding: 6 4 4 6;"; private static final int IMAGE_NEW_LINE_WIDTH = 10; private static final int IMAGE_FONT_SIZE = 15; DeckView() { final Button button = new Button(); button.setGraphic(new ImageView(CardImages.getBack())); button.setStyle(BUTTON_STYLE_NORMAL); button.setOnMousePressed(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent pEvent) { ((Button)pEvent.getSource()).setStyle(BUTTON_STYLE_PRESSED); } }); button.setOnMouseReleased(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent pEvent) { ((Button)pEvent.getSource()).setStyle(BUTTON_STYLE_NORMAL); if( GameModel.instance().isEmptyDeck() ) { GameModel.instance().reset(); } else { GameModel.instance().getDiscardMove().perform(); } } }); getChildren().add(button); GameModel.instance().addListener(this); } private Canvas createNewGameImage() { double width = CardImages.getBack().getWidth(); double height = CardImages.getBack().getHeight(); Canvas canvas = new Canvas( width, height ); GraphicsContext context = canvas.getGraphicsContext2D(); // The reset image context.setStroke(Color.DARKGREEN); context.setLineWidth(IMAGE_NEW_LINE_WIDTH); context.strokeOval(width/4, height/2-width/4 + IMAGE_FONT_SIZE, width/2, width/2); // The text context.setTextAlign(TextAlignment.CENTER); context.setTextBaseline(VPos.CENTER); context.setFill(Color.DARKKHAKI); context.setFont(Font.font(Font.getDefault().getName(), IMAGE_FONT_SIZE)); if( GameModel.instance().isCompleted() ) { context.fillText("You won!", Math.round(width/2), IMAGE_FONT_SIZE); } else { context.fillText("Give up?", Math.round(width/2), IMAGE_FONT_SIZE); } context.setTextAlign(TextAlignment.CENTER); return canvas; } @Override public void gameStateChanged() { if( GameModel.instance().isEmptyDeck() ) { ((Button)getChildren().get(0)).setGraphic(createNewGameImage()); } else { ((Button)getChildren().get(0)).setGraphic(new ImageView(CardImages.getBack())); } } public void reset() { getChildren().get(0).setVisible(true); } }