From d746a9600fb1f021db40694e01131f0361f278ed Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Fri, 13 Jan 2017 00:50:53 +0100
Subject: [PATCH] Fixed #55

---
 bin/de/bricked/ui/SettingsGUI.fxml            |  88 ++++++++++
 src/de/bricked/game/Game.java                 |  10 +-
 src/de/bricked/game/settings/Settings.java    | 163 +++++++++++-------
 src/de/bricked/ui/Controller.java             |  22 +++
 src/de/bricked/ui/LanguageType.java           |  18 ++
 src/de/bricked/ui/SettingsController.java     | 140 +++++++++++++++
 src/de/bricked/ui/SettingsGUI.fxml            |  88 ++++++++++
 .../ui/cells/ComboBoxLanguageCell.java        |  22 +++
 .../ui/cells/ComboBoxResolutionCell.java      |  29 ++++
 9 files changed, 515 insertions(+), 65 deletions(-)
 create mode 100644 bin/de/bricked/ui/SettingsGUI.fxml
 create mode 100644 src/de/bricked/ui/LanguageType.java
 create mode 100644 src/de/bricked/ui/SettingsController.java
 create mode 100644 src/de/bricked/ui/SettingsGUI.fxml
 create mode 100644 src/de/bricked/ui/cells/ComboBoxLanguageCell.java
 create mode 100644 src/de/bricked/ui/cells/ComboBoxResolutionCell.java

diff --git a/bin/de/bricked/ui/SettingsGUI.fxml b/bin/de/bricked/ui/SettingsGUI.fxml
new file mode 100644
index 0000000..d675278
--- /dev/null
+++ b/bin/de/bricked/ui/SettingsGUI.fxml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.ComboBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Slider?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.VBox?>
+<?import javafx.scene.text.Font?>
+
+<AnchorPane fx:id="mainPane" prefHeight="800.0" prefWidth="650.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.bricked.ui.SettingsController">
+   <children>
+      <Label layoutX="249.0" layoutY="24.0" text="Settings">
+         <font>
+            <Font name="System Bold" size="40.0" />
+         </font>
+      </Label>
+      <VBox prefHeight="649.0" prefWidth="590.0" AnchorPane.bottomAnchor="36.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0">
+         <children>
+            <HBox prefHeight="643.0" prefWidth="622.0">
+               <children>
+                  <VBox alignment="TOP_CENTER" spacing="50.0" HBox.hgrow="ALWAYS">
+                     <children>
+                        <Label text="Resolution:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                        <Label text="Language:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                        <Label text="Sound:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                     </children>
+                  </VBox>
+                  <VBox spacing="50.0" HBox.hgrow="ALWAYS">
+                     <children>
+                        <ComboBox fx:id="comboBoxResolution" prefHeight="35.0" prefWidth="290.0" />
+                        <ComboBox fx:id="comboBoxLanguage" prefHeight="35.0" prefWidth="290.0" />
+                        <CheckBox fx:id="checkBoxSound" mnemonicParsing="false" prefHeight="35.0" text="Activated">
+                           <font>
+                              <Font name="System Bold" size="18.0" />
+                           </font>
+                        </CheckBox>
+                        <Slider fx:id="sliderVolume" maxWidth="290.0" minorTickCount="4" prefHeight="35.0" prefWidth="290.0" showTickLabels="true" showTickMarks="true">
+                           <VBox.margin>
+                              <Insets top="-30.0" />
+                           </VBox.margin>
+                        </Slider>
+                     </children>
+                     <HBox.margin>
+                        <Insets />
+                     </HBox.margin>
+                     <padding>
+                        <Insets right="25.0" />
+                     </padding>
+                  </VBox>
+               </children>
+            </HBox>
+            <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
+               <children>
+                  <Button fx:id="buttonBack" minHeight="42.0" minWidth="154.0" mnemonicParsing="false" onAction="#back" prefHeight="42.0" prefWidth="150.0" text="Back">
+                     <font>
+                        <Font name="System Bold" size="20.0" />
+                     </font>
+                  </Button>
+                  <Button fx:id="buttonSave" minHeight="42.0" minWidth="141.0" mnemonicParsing="false" onAction="#save" prefHeight="42.0" prefWidth="150.0" text="Save" textAlignment="CENTER">
+                     <font>
+                        <Font name="System Bold" size="20.0" />
+                     </font>
+                     <HBox.margin>
+                        <Insets left="50.0" />
+                     </HBox.margin>
+                  </Button>
+               </children>
+            </HBox>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>
diff --git a/src/de/bricked/game/Game.java b/src/de/bricked/game/Game.java
index 649c062..204ee6a 100644
--- a/src/de/bricked/game/Game.java
+++ b/src/de/bricked/game/Game.java
@@ -35,9 +35,8 @@ public class Game
 
 	public Game()
 	{
-		this.settings = new Settings();
-		//DEBUG values in constructor should be loaded from settings
-		this.soundHandler = new SoundHandler(1.0, false);		
+		this.settings = new Settings(true);			
+		this.soundHandler = new SoundHandler(settings.getVolume(), settings.isMuted());			
 		this.levelPack = null;
 		this.level = null;
 		this.livesRemaining = 0;
@@ -186,6 +185,11 @@ public class Game
 	public SoundHandler getSoundHandler()
 	{
 		return soundHandler;
+	}	
+
+	public void refreshSoundHandler()
+	{
+		soundHandler = new SoundHandler(settings.getVolume(), settings.isMuted());
 	}
 
 	public Point2D reflectBall(HitLocation hitLocation, Point2D direction)
diff --git a/src/de/bricked/game/settings/Settings.java b/src/de/bricked/game/settings/Settings.java
index 3c571c5..b88cd0c 100644
--- a/src/de/bricked/game/settings/Settings.java
+++ b/src/de/bricked/game/settings/Settings.java
@@ -1,6 +1,8 @@
 package de.bricked.game.settings;
+
 import com.google.gson.Gson;
 import de.bricked.game.Config;
+import de.bricked.ui.LanguageType;
 import logger.LogLevel;
 import logger.Logger;
 import tools.PathUtils;
@@ -12,66 +14,77 @@ import java.nio.file.Files;
 
 public class Settings
 {
-    private GameSize gameSize;
-    private String language; //TODO change this to lanugage class maybe?
-    private double volume;
-    private boolean muted;
-    private transient final String filename = "settings.json";
-    private transient Gson gson;
-    private transient File file;
-
-    public Settings()
-    {
-        gson = new Gson();
-        PathUtils.checkFolder(new File(Config.FILESYSTEM_ROOT_DIR));
-        file = new File(Config.FILESYSTEM_ROOT_DIR + filename);
-        initDefaultSettings();
-    }
-
-    private void initDefaultSettings()
-    {
-        gameSize = GameSize.NORMAL;
-        language = "eng";
-        muted = false;
-        volume = 0.5;
-    }
-
-    public void save()
-    {
-        try
-        {
-            FileWriter fileWriter = new FileWriter(file);
-            String json = gson.toJson(this);
-            fileWriter.write(json);
-            fileWriter.flush();
-            fileWriter.close();
-        }
-        catch (Exception e)
-        {
-            Logger.log(LogLevel.ERROR, Logger.exceptionToString(e));
-        }
-    }
-
-    public void load()
-    {
-        try
-        {
-            String jsonContent = new String(Files.readAllBytes(FileSystems.getDefault().getPath(Config.FILESYSTEM_ROOT_DIR + filename)));
-            System.out.println(jsonContent);
-            Settings loadedSettings = gson.fromJson(jsonContent, Settings.class);
-            this.gameSize = loadedSettings.gameSize;
-            this.language = loadedSettings.language;
-            this.muted = loadedSettings.muted;
-            this.volume = loadedSettings.volume;
-            // MORE settings go here
-
-        }
-        catch (Exception e)
-        {
-            Logger.log(LogLevel.ERROR, Logger.exceptionToString(e));
-        }
-
-    }
+	private GameSize gameSize;
+	private LanguageType language;
+	private double volume;
+	private boolean muted;
+	private transient final String filename = "settings.json";
+	private transient Gson gson;
+	private transient File file;
+
+	public Settings(boolean init)
+	{
+		gson = new Gson();
+		PathUtils.checkFolder(new File(Config.FILESYSTEM_ROOT_DIR));
+		file = new File(Config.FILESYSTEM_ROOT_DIR + filename);
+		if(file.exists())
+		{
+			load();
+		}
+		else
+		{
+			initDefaultSettings();
+			save();
+		}
+	}
+	
+	//needed for GSON de-serialization
+	public Settings()
+	{
+		
+	}
+
+	private void initDefaultSettings()
+	{
+		gameSize = GameSize.NORMAL;
+		language = LanguageType.ENGLISH;
+		muted = false;
+		volume = 0.5;
+	}
+
+	public void save()
+	{
+		try
+		{
+			FileWriter fileWriter = new FileWriter(file);
+			String json = gson.toJson(this);
+			fileWriter.write(json);
+			fileWriter.flush();
+			fileWriter.close();
+		}
+		catch(Exception e)
+		{
+			Logger.log(LogLevel.ERROR, Logger.exceptionToString(e));
+		}
+	}
+
+	public void load()
+	{
+		try
+		{
+			String jsonContent = new String(Files.readAllBytes(FileSystems.getDefault().getPath(Config.FILESYSTEM_ROOT_DIR + filename)));			
+			Settings loadedSettings = gson.fromJson(jsonContent, Settings.class);
+			this.gameSize = loadedSettings.gameSize;
+			this.language = loadedSettings.language;
+			this.muted = loadedSettings.muted;
+			this.volume = loadedSettings.volume;
+			// MORE settings go here
+		}
+		catch(Exception e)
+		{
+			Logger.log(LogLevel.ERROR, Logger.exceptionToString(e));
+		}
+	}
 
 	public GameSize getGameSize()
 	{
@@ -83,13 +96,39 @@ public class Settings
 		this.gameSize = gameSize;
 	}
 
-	public String getLanguage()
+	public LanguageType getLanguage()
 	{
 		return language;
 	}
 
-	public void setLanguage(String language)
+	public void setLanguage(LanguageType language)
 	{
 		this.language = language;
 	}
+
+	public double getVolume()
+	{
+		return volume;
+	}
+
+	public void setVolume(double volume)
+	{
+		this.volume = volume;
+	}
+
+	public boolean isMuted()
+	{
+		return muted;
+	}
+
+	public void setMuted(boolean muted)
+	{
+		this.muted = muted;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "Settings [gameSize=" + gameSize + ", language=" + language + ", volume=" + volume + ", muted=" + muted + "]";
+	}
 }
\ No newline at end of file
diff --git a/src/de/bricked/ui/Controller.java b/src/de/bricked/ui/Controller.java
index eee193f..0e9cd99 100644
--- a/src/de/bricked/ui/Controller.java
+++ b/src/de/bricked/ui/Controller.java
@@ -110,7 +110,29 @@ public class Controller
 	
 	public void showSettings()
 	{
+		try
+		{
+			FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/de/bricked/ui/SettingsGUI.fxml"));
+
+			Parent root = (Parent)fxmlLoader.load();
+			Stage newStage = new Stage();
+			newStage.setScene(new Scene(root, 650, 800));		
+			newStage.setTitle(bundle.getString("app.name") + " - Settings");
+			newStage.initOwner(stage);
+
+			newStage.getIcons().add(icon);			
+			SettingsController newController = fxmlLoader.getController();
+			newController.init(newStage, this, game);		
 
+			newStage.initModality(Modality.NONE);
+			newStage.setResizable(false);
+			stage.hide();
+			newStage.show();
+		}
+		catch(IOException e1)
+		{
+			e1.printStackTrace();
+		}
 	}
 	
 	public void showAchievements()
diff --git a/src/de/bricked/ui/LanguageType.java b/src/de/bricked/ui/LanguageType.java
new file mode 100644
index 0000000..c318170
--- /dev/null
+++ b/src/de/bricked/ui/LanguageType.java
@@ -0,0 +1,18 @@
+package de.bricked.ui;
+
+public enum LanguageType
+{
+	ENGLISH("English");
+	
+	private String name;
+	
+	private LanguageType(String name)
+	{
+		this.name = name;
+	}
+
+	public String getName()
+	{
+		return name;
+	}
+}
\ No newline at end of file
diff --git a/src/de/bricked/ui/SettingsController.java b/src/de/bricked/ui/SettingsController.java
new file mode 100644
index 0000000..69e0c44
--- /dev/null
+++ b/src/de/bricked/ui/SettingsController.java
@@ -0,0 +1,140 @@
+package de.bricked.ui;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import de.bricked.game.Game;
+import de.bricked.game.settings.GameSize;
+import de.bricked.ui.cells.ComboBoxLanguageCell;
+import de.bricked.ui.cells.ComboBoxResolutionCell;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.control.Slider;
+import javafx.scene.image.Image;
+import javafx.scene.layout.AnchorPane;
+import javafx.stage.Stage;
+import javafx.util.Callback;
+import logger.LogLevel;
+import logger.Logger;
+
+public class SettingsController
+{
+	@FXML private AnchorPane mainPane;
+	@FXML private Label labelLevelPack;
+	@FXML private Button buttonBack;
+	@FXML private Button buttonSave;
+	@FXML private ComboBox<GameSize> comboBoxResolution;
+	@FXML private ComboBox<LanguageType> comboBoxLanguage;
+	@FXML private CheckBox checkBoxSound;
+	@FXML private Slider sliderVolume;
+
+	public Stage stage;
+	public Image icon = new Image("de/bricked/resources/icon.png");
+	public final ResourceBundle bundle = ResourceBundle.getBundle("de/bricked/main/", Locale.GERMANY);
+	public Controller controller;
+	public Game game;
+
+	public void init(Stage stage, Controller controller, Game game)
+	{
+		this.stage = stage;
+		this.controller = controller;
+		this.game = game;
+
+		comboBoxResolution.setCellFactory(new Callback<ListView<GameSize>, ListCell<GameSize>>()
+		{			
+			@Override
+			public ListCell<GameSize> call(ListView<GameSize> param)
+			{
+				return new ComboBoxResolutionCell();
+			}
+		});
+		comboBoxResolution.setButtonCell(new ComboBoxResolutionCell());
+		comboBoxResolution.getItems().addAll(GameSize.values());
+		
+		comboBoxLanguage.setCellFactory(new Callback<ListView<LanguageType>, ListCell<LanguageType>>()
+		{			
+			@Override
+			public ListCell<LanguageType> call(ListView<LanguageType> param)
+			{
+				return new ComboBoxLanguageCell();
+			}
+		});
+		comboBoxLanguage.setButtonCell(new ComboBoxLanguageCell());
+		comboBoxLanguage.getItems().addAll(LanguageType.values());	
+		
+		checkBoxSound.selectedProperty().addListener(new ChangeListener<Boolean>()
+		{
+			@Override
+			public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
+			{
+				if(newValue == true)
+				{
+					sliderVolume.setDisable(false);
+				}
+				else
+				{
+					sliderVolume.setDisable(true);
+				}				
+			}
+		});
+		
+		//preselect
+		comboBoxResolution.setValue(game.getSettings().getGameSize());
+		comboBoxLanguage.setValue(game.getSettings().getLanguage());
+		if(game.getSettings().isMuted())
+		{
+			checkBoxSound.setSelected(false);
+			sliderVolume.setDisable(true);
+		}
+		else
+		{
+			checkBoxSound.setSelected(true);
+			sliderVolume.setDisable(false);
+		}
+		sliderVolume.setValue(game.getSettings().getVolume() * 100);
+		
+		mainPane.setStyle("-fx-base: " + bundle.getString("color.background") + ";");
+	}
+
+	public void save()
+	{
+		game.getSettings().setGameSize(comboBoxResolution.getValue());
+		game.getSettings().setLanguage(comboBoxLanguage.getValue());
+		game.getSettings().setMuted(!checkBoxSound.isSelected());
+		game.getSettings().setVolume(sliderVolume.getValue() / 100.0);
+		game.getSettings().save();
+		
+		game.refreshSoundHandler();
+		stage.close();
+		controller.stage.show();
+		
+		//TODO load correct language file
+	}
+
+	public void back()
+	{
+		stage.close();
+		controller.stage.show();
+	}
+
+	public void showCommandLine()
+	{
+		try
+		{
+			controller.getCommandLine().showCommandLine("Debug Console", 400, 250, 400, 200, -1, -1, true);
+		}
+		catch(IOException e)
+		{
+			// TODO: errorhandling
+			Logger.log(LogLevel.ERROR, Logger.exceptionToString(e));
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/de/bricked/ui/SettingsGUI.fxml b/src/de/bricked/ui/SettingsGUI.fxml
new file mode 100644
index 0000000..d675278
--- /dev/null
+++ b/src/de/bricked/ui/SettingsGUI.fxml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.ComboBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Slider?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.VBox?>
+<?import javafx.scene.text.Font?>
+
+<AnchorPane fx:id="mainPane" prefHeight="800.0" prefWidth="650.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.bricked.ui.SettingsController">
+   <children>
+      <Label layoutX="249.0" layoutY="24.0" text="Settings">
+         <font>
+            <Font name="System Bold" size="40.0" />
+         </font>
+      </Label>
+      <VBox prefHeight="649.0" prefWidth="590.0" AnchorPane.bottomAnchor="36.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0">
+         <children>
+            <HBox prefHeight="643.0" prefWidth="622.0">
+               <children>
+                  <VBox alignment="TOP_CENTER" spacing="50.0" HBox.hgrow="ALWAYS">
+                     <children>
+                        <Label text="Resolution:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                        <Label text="Language:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                        <Label text="Sound:">
+                           <font>
+                              <Font name="System Bold" size="25.0" />
+                           </font>
+                        </Label>
+                     </children>
+                  </VBox>
+                  <VBox spacing="50.0" HBox.hgrow="ALWAYS">
+                     <children>
+                        <ComboBox fx:id="comboBoxResolution" prefHeight="35.0" prefWidth="290.0" />
+                        <ComboBox fx:id="comboBoxLanguage" prefHeight="35.0" prefWidth="290.0" />
+                        <CheckBox fx:id="checkBoxSound" mnemonicParsing="false" prefHeight="35.0" text="Activated">
+                           <font>
+                              <Font name="System Bold" size="18.0" />
+                           </font>
+                        </CheckBox>
+                        <Slider fx:id="sliderVolume" maxWidth="290.0" minorTickCount="4" prefHeight="35.0" prefWidth="290.0" showTickLabels="true" showTickMarks="true">
+                           <VBox.margin>
+                              <Insets top="-30.0" />
+                           </VBox.margin>
+                        </Slider>
+                     </children>
+                     <HBox.margin>
+                        <Insets />
+                     </HBox.margin>
+                     <padding>
+                        <Insets right="25.0" />
+                     </padding>
+                  </VBox>
+               </children>
+            </HBox>
+            <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
+               <children>
+                  <Button fx:id="buttonBack" minHeight="42.0" minWidth="154.0" mnemonicParsing="false" onAction="#back" prefHeight="42.0" prefWidth="150.0" text="Back">
+                     <font>
+                        <Font name="System Bold" size="20.0" />
+                     </font>
+                  </Button>
+                  <Button fx:id="buttonSave" minHeight="42.0" minWidth="141.0" mnemonicParsing="false" onAction="#save" prefHeight="42.0" prefWidth="150.0" text="Save" textAlignment="CENTER">
+                     <font>
+                        <Font name="System Bold" size="20.0" />
+                     </font>
+                     <HBox.margin>
+                        <Insets left="50.0" />
+                     </HBox.margin>
+                  </Button>
+               </children>
+            </HBox>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>
diff --git a/src/de/bricked/ui/cells/ComboBoxLanguageCell.java b/src/de/bricked/ui/cells/ComboBoxLanguageCell.java
new file mode 100644
index 0000000..89b359d
--- /dev/null
+++ b/src/de/bricked/ui/cells/ComboBoxLanguageCell.java
@@ -0,0 +1,22 @@
+package de.bricked.ui.cells;
+
+import de.bricked.ui.LanguageType;
+import javafx.scene.control.cell.ComboBoxListCell;
+
+public class ComboBoxLanguageCell extends ComboBoxListCell<LanguageType>
+{	
+	@Override
+	public void updateItem(LanguageType item, boolean empty)
+	{
+		super.updateItem(item, empty);
+
+		if( ! empty)
+		{	
+			setText(item.getName());					
+		}
+		else
+		{
+			setText(null);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/de/bricked/ui/cells/ComboBoxResolutionCell.java b/src/de/bricked/ui/cells/ComboBoxResolutionCell.java
new file mode 100644
index 0000000..9ebecf8
--- /dev/null
+++ b/src/de/bricked/ui/cells/ComboBoxResolutionCell.java
@@ -0,0 +1,29 @@
+package de.bricked.ui.cells;
+
+import de.bricked.game.settings.GameSize;
+import javafx.scene.control.cell.ComboBoxListCell;
+
+public class ComboBoxResolutionCell extends ComboBoxListCell<GameSize>
+{	
+	@Override
+	public void updateItem(GameSize item, boolean empty)
+	{
+		super.updateItem(item, empty);
+
+		if( ! empty)
+		{	
+			if(item == GameSize.FULL_SCREEN)
+			{
+				setText("Fullscreen");
+			}
+			else
+			{
+				setText(item.getWidth() + " x " + item.getHeight());
+			}			
+		}
+		else
+		{
+			setText(null);
+		}
+	}
+}
\ No newline at end of file
-- 
GitLab