1432 lines
50 KiB
Java
1432 lines
50 KiB
Java
/**
|
|
* cemu_UI
|
|
*
|
|
* Copyright 2017-2019 <@Seil0>
|
|
*
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
package com.cemu_UI.application;
|
|
|
|
import java.awt.Graphics2D;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.math.BigInteger;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.sql.SQLException;
|
|
import java.time.LocalDate;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.ArrayList;
|
|
import java.util.Locale;
|
|
import java.util.Properties;
|
|
import java.util.ResourceBundle;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import javax.swing.ProgressMonitor;
|
|
import javax.swing.ProgressMonitorInputStream;
|
|
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
import com.cemu_UI.controller.DBController;
|
|
import com.cemu_UI.controller.SmmdbAPIController;
|
|
import com.cemu_UI.controller.UpdateController;
|
|
import com.cemu_UI.controller.XMLController;
|
|
import com.cemu_UI.datatypes.CourseTableDataType;
|
|
import com.cemu_UI.datatypes.GlobalDataTypes.CloudService;
|
|
import com.cemu_UI.datatypes.SmmdbApiDataType;
|
|
import com.cemu_UI.datatypes.UIROMDataType;
|
|
import com.cemu_UI.uiElements.JFXEditGameAlert;
|
|
import com.cemu_UI.uiElements.JFXInfoAlert;
|
|
import com.cemu_UI.uiElements.JFXOkayCancelAlert;
|
|
import com.cemu_UI.uiElements.JFXTextAreaAlert;
|
|
import com.jfoenix.controls.JFXButton;
|
|
import com.jfoenix.controls.JFXColorPicker;
|
|
import com.jfoenix.controls.JFXHamburger;
|
|
import com.jfoenix.controls.JFXSpinner;
|
|
import com.jfoenix.controls.JFXTextField;
|
|
import com.jfoenix.controls.JFXToggleButton;
|
|
import com.jfoenix.controls.JFXTreeTableColumn;
|
|
import com.jfoenix.controls.JFXTreeTableView;
|
|
import com.jfoenix.transitions.hamburger.HamburgerBackArrowBasicTransition;
|
|
|
|
import javafx.animation.TranslateTransition;
|
|
import javafx.application.Platform;
|
|
import javafx.beans.value.ChangeListener;
|
|
import javafx.beans.value.ObservableValue;
|
|
import javafx.collections.FXCollections;
|
|
import javafx.collections.ObservableList;
|
|
import javafx.event.ActionEvent;
|
|
import javafx.event.EventHandler;
|
|
import javafx.fxml.FXML;
|
|
import javafx.scene.control.ChoiceBox;
|
|
import javafx.scene.control.ContextMenu;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.MenuItem;
|
|
import javafx.scene.control.ScrollPane;
|
|
import javafx.scene.control.TreeItem;
|
|
import javafx.scene.image.Image;
|
|
import javafx.scene.image.ImageView;
|
|
import javafx.scene.input.MouseButton;
|
|
import javafx.scene.input.MouseEvent;
|
|
import javafx.scene.layout.AnchorPane;
|
|
import javafx.scene.layout.FlowPane;
|
|
import javafx.scene.layout.HBox;
|
|
import javafx.scene.layout.VBox;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.paint.Paint;
|
|
import javafx.scene.text.Font;
|
|
import javafx.scene.text.FontWeight;
|
|
import javafx.scene.text.Text;
|
|
import javafx.scene.text.TextFlow;
|
|
import javafx.stage.DirectoryChooser;
|
|
import javafx.stage.Stage;
|
|
import javafx.util.Duration;
|
|
import net.lingala.zip4j.core.ZipFile;
|
|
import net.lingala.zip4j.exception.ZipException;
|
|
|
|
public class MainWindowController {
|
|
|
|
@FXML private JFXButton aboutBtn;
|
|
@FXML private JFXButton settingsBtn;
|
|
@FXML private JFXButton addBtn;
|
|
@FXML private JFXButton reloadRomsBtn;
|
|
@FXML private JFXButton smmdbBtn;
|
|
@FXML private JFXButton cemuTFBtn;
|
|
@FXML private JFXButton romTFBtn;
|
|
@FXML private JFXButton updateBtn;
|
|
@FXML private JFXButton smmdbDownloadBtn;
|
|
@FXML private JFXButton playBtn;
|
|
@FXML private JFXButton lastTimePlayedBtn;
|
|
@FXML JFXButton totalPlaytimeBtn;
|
|
|
|
@FXML private JFXHamburger menuHam;
|
|
|
|
@FXML private JFXTextField cemuTextField;
|
|
@FXML private JFXTextField romTextField;
|
|
@FXML private JFXTextField courseSearchTextFiled;
|
|
@FXML private JFXTextField executeCommandTextFiled;
|
|
|
|
@FXML private TextFlow smmdbTextFlow;
|
|
|
|
@FXML private JFXColorPicker colorPicker;
|
|
|
|
@FXML private JFXToggleButton cloudSyncToggleBtn;
|
|
@FXML private JFXToggleButton autoUpdateToggleBtn;
|
|
@FXML private JFXToggleButton fullscreenToggleBtn;
|
|
|
|
@FXML private ChoiceBox<String> languageChoisBox;
|
|
@FXML private ChoiceBox<String> branchChoisBox;
|
|
|
|
@FXML private ScrollPane mainScrollPane;
|
|
@FXML private ScrollPane settingsScrollPane;
|
|
@FXML private ScrollPane smmdbScrollPane;
|
|
@FXML private ScrollPane smmdbImageViewScrollPane;
|
|
|
|
@FXML private AnchorPane mainAnchorPane;
|
|
@FXML private AnchorPane settingsAnchorPane;
|
|
@FXML private AnchorPane smmdbAnchorPane;
|
|
|
|
@FXML private FlowPane gamesFlowPane;
|
|
|
|
@FXML private VBox sideMenuVBox;
|
|
|
|
@FXML private HBox topHBox;
|
|
@FXML private HBox bottomHBox;
|
|
|
|
@FXML private ImageView smmdbImageView;
|
|
|
|
@FXML private Label helpLbl;
|
|
@FXML private Label cemu_UISettingsLbl;
|
|
@FXML private Label cemuDirectoryLbl;
|
|
@FXML private Label romDirectoryLbl;
|
|
@FXML private Label mainColorLbl;
|
|
@FXML private Label languageLbl;
|
|
@FXML private Label updateLbl;
|
|
@FXML private Label branchLbl;
|
|
@FXML private Label cemuSettingsLbl;
|
|
@FXML private Label licensesLbl;
|
|
|
|
@FXML private JFXTreeTableView<CourseTableDataType> courseTreeTable = new JFXTreeTableView<CourseTableDataType>();
|
|
|
|
@FXML private TreeItem<CourseTableDataType> root = new TreeItem<>(new CourseTableDataType("", "", 0, 0));
|
|
|
|
@FXML private JFXTreeTableColumn<CourseTableDataType, String> titleColumn = new JFXTreeTableColumn<>("title");
|
|
@FXML private JFXTreeTableColumn<CourseTableDataType, String> idColumn = new JFXTreeTableColumn<>("id");
|
|
@FXML private JFXTreeTableColumn<CourseTableDataType, Integer> starsColumn = new JFXTreeTableColumn<>("stars");
|
|
@FXML private JFXTreeTableColumn<CourseTableDataType, Integer> timeColumn = new JFXTreeTableColumn<>("time");
|
|
|
|
private Main main;
|
|
private DBController dbController;
|
|
private SmmdbAPIController smmdbAPIController;
|
|
private playGame playGame;
|
|
private static MainWindowController MWC;
|
|
private UpdateController updateController;
|
|
private XMLController xmlController;
|
|
private Stage primaryStage;
|
|
private boolean menuTrue = false;
|
|
private boolean playTrue = false;
|
|
private String gameExecutePath;
|
|
private String btnStyle;
|
|
private String selectedGameTitleID;
|
|
private String selectedGameTitle;
|
|
private String id;
|
|
private String version = "0.3.2";
|
|
private String buildNumber = "085";
|
|
private String versionName = "Purple Comet";
|
|
private int selectedUIDataIndex;
|
|
private int selected;
|
|
private DirectoryChooser directoryChooser = new DirectoryChooser();
|
|
private ObservableList<String> branches = FXCollections.observableArrayList("stable", "beta");
|
|
private ObservableList<String> languages = FXCollections.observableArrayList("English (en_US)", "Deutsch (de_DE)");
|
|
private ObservableList<String> smmIDs = FXCollections.observableArrayList("fe31b7f2", "44fc5929");
|
|
private ObservableList<UIROMDataType> games = FXCollections.observableArrayList();
|
|
ObservableList<SmmdbApiDataType> courses = FXCollections.observableArrayList();
|
|
ObservableList<SmmdbApiDataType> filteredCourses = FXCollections.observableArrayList();
|
|
ArrayList<Text> courseText = new ArrayList<Text>();
|
|
ArrayList<Text> nameText = new ArrayList<Text>();
|
|
Properties props = new Properties();
|
|
Properties gameProps = new Properties();
|
|
private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName());
|
|
private HamburgerBackArrowBasicTransition burgerTask;
|
|
private MenuItem edit = new MenuItem("edit");
|
|
private MenuItem remove = new MenuItem("remove");
|
|
private MenuItem addUpdate = new MenuItem("update");
|
|
private MenuItem addDLC = new MenuItem("add DLC");
|
|
private ContextMenu gameContextMenu = new ContextMenu(edit, remove, addUpdate, addDLC);
|
|
private Label lastGameLabel = new Label();
|
|
|
|
// language support
|
|
private String lastPlayed;
|
|
private String today;
|
|
private String yesterday;
|
|
private String never;
|
|
|
|
public MainWindowController(Main main) {
|
|
xmlController = new XMLController();
|
|
this.main = main;
|
|
dbController = DBController.getInstance();
|
|
smmdbAPIController = new SmmdbAPIController();
|
|
}
|
|
|
|
/**
|
|
* initialize the MainWindowController
|
|
* loadSettings, checkAutoUpdate, initUI and initActions
|
|
*/
|
|
public void init() {
|
|
xmlController.loadSettings(); // load settings
|
|
checkAutoUpdate();
|
|
initUI();
|
|
initActions();
|
|
|
|
dbController.init();
|
|
dbController.refreshDataBase();
|
|
games = dbController.loadAllGames();
|
|
addAllGames();
|
|
}
|
|
|
|
/**
|
|
* initialize all variable UI parameters and elements
|
|
*/
|
|
private void initUI() {
|
|
LOGGER.info("initializing UI ...");
|
|
|
|
primaryStage = (Stage) mainAnchorPane.getScene().getWindow(); // set primary stage for dialogs
|
|
|
|
// TODO this is broken
|
|
if (XMLController.getWindowWidth() > 100 && XMLController.getWindowHeight() > 100) {
|
|
mainAnchorPane.setPrefSize(XMLController.getWindowWidth(), XMLController.getWindowHeight());
|
|
}
|
|
|
|
cemuTextField.setText(XMLController.getCemuPath());
|
|
romTextField.setText(XMLController.getRomDirectoryPath());
|
|
colorPicker.setValue(Color.valueOf(XMLController.getColor()));
|
|
fullscreenToggleBtn.setSelected(XMLController.isFullscreen());
|
|
cloudSyncToggleBtn.setSelected(XMLController.isCloudSync());
|
|
autoUpdateToggleBtn.setSelected(XMLController.isAutoUpdate());
|
|
branchChoisBox.setItems(branches);
|
|
languageChoisBox.setItems(languages);
|
|
bottomHBox.setPickOnBounds(false);
|
|
|
|
if (XMLController.isUseBeta()) {
|
|
branchChoisBox.getSelectionModel().select(1);
|
|
} else {
|
|
branchChoisBox.getSelectionModel().select(0);
|
|
}
|
|
|
|
applyColor();
|
|
|
|
// initialize courseTable
|
|
titleColumn.setPrefWidth(185);
|
|
timeColumn.setPrefWidth(112);
|
|
starsColumn.setPrefWidth(90);
|
|
|
|
courseTreeTable.setRoot(root);
|
|
courseTreeTable.setShowRoot(false);
|
|
courseTreeTable.setEditable(false);
|
|
|
|
titleColumn.setCellValueFactory(cellData -> cellData.getValue().getValue().title);
|
|
idColumn.setCellValueFactory(cellData -> cellData.getValue().getValue().id);
|
|
starsColumn.setCellValueFactory(cellData -> cellData.getValue().getValue().stars.asObject());
|
|
timeColumn.setCellValueFactory(cellData -> cellData.getValue().getValue().time.asObject());
|
|
|
|
courseTreeTable.getColumns().add(titleColumn);
|
|
courseTreeTable.getColumns().add(timeColumn);
|
|
courseTreeTable.getColumns().add(starsColumn);
|
|
courseTreeTable.getColumns().add(idColumn);
|
|
courseTreeTable.getColumns().get(3).setVisible(false); // the idColumn should not bee displayed
|
|
|
|
setUILanguage();
|
|
|
|
LOGGER.info("initializing UI done");
|
|
}
|
|
|
|
/**
|
|
* initialize all actions not initialized by a own method
|
|
*/
|
|
private void initActions() {
|
|
LOGGER.info("initializing Actions ...");
|
|
|
|
MWC = this;
|
|
burgerTask = new HamburgerBackArrowBasicTransition(menuHam);
|
|
menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, (e)->{
|
|
if (playTrue) {
|
|
playBtnSlideOut();
|
|
}
|
|
|
|
if (menuTrue) {
|
|
sideMenuSlideOut();
|
|
burgerTask.setRate(-1.0);
|
|
burgerTask.play();
|
|
menuTrue = false;
|
|
} else {
|
|
sideMenuSlideIn();
|
|
burgerTask.setRate(1.0);
|
|
burgerTask.play();
|
|
menuTrue = true;
|
|
}
|
|
|
|
if (settingsScrollPane.isVisible()) {
|
|
settingsScrollPane.setVisible(false);
|
|
xmlController.saveSettings();
|
|
}
|
|
|
|
if (smmdbAnchorPane.isVisible()) {
|
|
smmdbAnchorPane.setVisible(false);
|
|
}
|
|
});
|
|
|
|
edit.setOnAction(event -> {
|
|
try {
|
|
LOGGER.info("edit " + selectedGameTitleID);
|
|
String[] gameInfo = dbController.getGameInfo(selectedGameTitleID);
|
|
|
|
// new edit dialog
|
|
String headingText = XMLController.getLocalBundle().getString("editHeadingText") + " \"" + selectedGameTitle + "\"";
|
|
JFXEditGameAlert editGameAlert = new JFXEditGameAlert(headingText,
|
|
XMLController.getLocalBundle().getString("editBodyText"), btnStyle, 1, primaryStage, MWC);
|
|
editGameAlert.setTitle(gameInfo[0]);
|
|
editGameAlert.setCoverPath(gameInfo[1]);
|
|
editGameAlert.setRomPath(gameInfo[2]);
|
|
editGameAlert.setTitleID(gameInfo[3]);
|
|
editGameAlert.showAndWait();
|
|
} catch (Exception e) {
|
|
LOGGER.warn("trying to edit " + selectedGameTitleID + ",which is not a valid type!", e);
|
|
}
|
|
});
|
|
|
|
remove.setOnAction(event -> {
|
|
try {
|
|
LOGGER.info("remove " + selectedGameTitle + "(" + selectedGameTitleID + ")");
|
|
String headingText = XMLController.getLocalBundle().getString("removeHeadingText") + " \"" + selectedGameTitle + "\"";
|
|
String bodyText = XMLController.getLocalBundle().getString("removeBodyText") + " " + selectedGameTitle + " ?";
|
|
JFXOkayCancelAlert removeGameAlert = new JFXOkayCancelAlert(headingText, bodyText, btnStyle,
|
|
primaryStage);
|
|
removeGameAlert.setOkayAction(e -> {
|
|
try {
|
|
games.remove(selectedUIDataIndex); // remove game form games-list
|
|
dbController.removeGame(selectedGameTitleID); // remove game from database
|
|
refreshUIData(); // refresh all games at gamesAnchorPane (UI)
|
|
} catch (Exception ex) {
|
|
LOGGER.error("error while removing ROM from database!", ex);
|
|
}
|
|
});
|
|
removeGameAlert.setCancelAction(e -> LOGGER.info("Action canceld by user!"));
|
|
removeGameAlert.showAndWait();
|
|
} catch (Exception e) {
|
|
LOGGER.error("error while removing " + selectedGameTitle + "(" + selectedGameTitleID + ")", e);
|
|
}
|
|
});
|
|
|
|
addUpdate.setOnAction(new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
try {
|
|
LOGGER.info("update: " + selectedGameTitleID);
|
|
|
|
EventHandler<ActionEvent> okayAction = new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
DirectoryChooser directoryChooser = new DirectoryChooser();
|
|
File selectedDirecroty = directoryChooser.showDialog(primaryStage);
|
|
String updatePath = selectedDirecroty.getAbsolutePath();
|
|
String[] parts = selectedGameTitleID.split("-"); // split string into 2 parts at "-"
|
|
File srcDir = new File(updatePath);
|
|
File destDir = new File(XMLController.getCemuPath() + "/mlc01/usr/title/" + parts[0] + "/" + parts[1]);
|
|
|
|
// if directory doesn't exist create it
|
|
if (destDir.exists() != true) {
|
|
destDir.mkdir();
|
|
}
|
|
|
|
try {
|
|
LOGGER.info("copying the content of " + updatePath + " to " + destDir.toString());
|
|
playBtn.setText(XMLController.getLocalBundle().getString("playBtnUpdating"));
|
|
playBtn.setDisable(true);
|
|
FileUtils.copyDirectory(srcDir, destDir);
|
|
playBtn.setText(XMLController.getLocalBundle().getString("playBtnPlay"));
|
|
playBtn.setDisable(false);
|
|
LOGGER.info("copying files done!");
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
};
|
|
|
|
EventHandler<ActionEvent> cancelAction = new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
LOGGER.info("Action canceld by user!");
|
|
}
|
|
};
|
|
|
|
String headingText = XMLController.getLocalBundle().getString("addUpdateHeadingText") + " \"" + selectedGameTitle + "\"";
|
|
JFXOkayCancelAlert updateGameAlert = new JFXOkayCancelAlert(headingText,
|
|
XMLController.getLocalBundle().getString("addUpdateBodyText"), btnStyle, primaryStage);
|
|
updateGameAlert.setOkayAction(okayAction);
|
|
updateGameAlert.setCancelAction(cancelAction);
|
|
updateGameAlert.showAndWait();
|
|
} catch (Exception e) {
|
|
LOGGER.warn("trying to update " + selectedGameTitleID + ",which is not a valid type!", e);
|
|
}
|
|
}
|
|
});
|
|
|
|
addDLC.setOnAction(new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
try {
|
|
LOGGER.info("add DLC: " + selectedGameTitleID);
|
|
String headingText = XMLController.getLocalBundle().getString("addDLCHeadingText") + " \"" + selectedGameTitle + "\"";
|
|
EventHandler<ActionEvent> okayAction = new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
DirectoryChooser directoryChooser = new DirectoryChooser();
|
|
File selectedDirecroty = directoryChooser.showDialog(primaryStage);
|
|
String dlcPath = selectedDirecroty.getAbsolutePath();
|
|
String[] parts = selectedGameTitleID.split("-"); // split string into 2 parts at "-"
|
|
File srcDir = new File(dlcPath);
|
|
File destDir = new File(XMLController.getCemuPath() + "/mlc01/usr/title/" + parts[0] + "/" + parts[1] + "/aoc");
|
|
|
|
// if directory doesn't exist create it
|
|
if (destDir.exists() != true) {
|
|
destDir.mkdir();
|
|
}
|
|
|
|
try {
|
|
LOGGER.info("copying the content of " + dlcPath + " to " + destDir.toString());
|
|
playBtn.setText(XMLController.getLocalBundle().getString("playBtnCopyingFiles"));
|
|
playBtn.setDisable(true);
|
|
FileUtils.copyDirectory(srcDir, destDir);
|
|
playBtn.setText(XMLController.getLocalBundle().getString("playBtnPlay"));
|
|
playBtn.setDisable(false);
|
|
LOGGER.info("copying files done!");
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
};
|
|
|
|
EventHandler<ActionEvent> cancelAction = new EventHandler<ActionEvent>() {
|
|
@Override
|
|
public void handle(ActionEvent event) {
|
|
LOGGER.info("Action canceld by user!");
|
|
}
|
|
};
|
|
|
|
JFXOkayCancelAlert addDLCAlert = new JFXOkayCancelAlert(headingText,
|
|
XMLController.getLocalBundle().getString("addDLCBodyText"), btnStyle, primaryStage);
|
|
addDLCAlert.setOkayAction(okayAction);
|
|
addDLCAlert.setCancelAction(cancelAction);
|
|
addDLCAlert.showAndWait();
|
|
} catch (Exception e) {
|
|
LOGGER.warn("trying to add a dlc to " + selectedGameTitleID + ",which is not a valid type!", e);
|
|
}
|
|
}
|
|
});
|
|
|
|
gamesFlowPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
|
|
@Override
|
|
public void handle(MouseEvent event) {
|
|
if (playTrue) {
|
|
playBtnSlideOut();
|
|
}
|
|
}
|
|
});
|
|
|
|
topHBox.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
|
|
@Override
|
|
public void handle(MouseEvent event) {
|
|
if (playTrue) {
|
|
playBtnSlideOut();
|
|
}
|
|
}
|
|
});
|
|
|
|
courseSearchTextFiled.textProperty().addListener(new ChangeListener<String>() {
|
|
@Override
|
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
|
|
|
|
filteredCourses.removeAll(filteredCourses);
|
|
root.getChildren().remove(0, root.getChildren().size());
|
|
|
|
for (int i = 0; i < courses.size(); i++) {
|
|
if (courses.get(i).getTitle().toLowerCase().contains(courseSearchTextFiled.getText().toLowerCase())) {
|
|
// add data from courses to filteredCourses where title contains search input
|
|
filteredCourses.add(courses.get(i));
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < filteredCourses.size(); i++) {
|
|
CourseTableDataType helpCourse = new CourseTableDataType(filteredCourses.get(i).getTitle(),
|
|
filteredCourses.get(i).getId(), filteredCourses.get(i).getTime(),
|
|
filteredCourses.get(i).getStars());
|
|
|
|
root.getChildren().add(new TreeItem<CourseTableDataType>(helpCourse)); // add data to root-node
|
|
}
|
|
}
|
|
});
|
|
|
|
// Change-listener for TreeTable
|
|
courseTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
|
|
@Override
|
|
public void changed(ObservableValue<?> observable, Object oldVal, Object newVal) {
|
|
selected = courseTreeTable.getSelectionModel().getSelectedIndex(); // get selected item
|
|
|
|
id = idColumn.getCellData(selected); // get name of selected item
|
|
|
|
for (int i = 0; i < courses.size(); i++) {
|
|
if (courses.get(i).getId() == id) {
|
|
try {
|
|
URL url = new URL("https://smmdb.ddns.net/courseimg/" + id + "_full?v=1");
|
|
Image sourceImage = new Image(url.toURI().toString());
|
|
|
|
// scale image to 142px
|
|
double scalefactor = 142 / sourceImage.getHeight(); // calculate scaling factor
|
|
int nWidth = (int) Math.rint(scalefactor * sourceImage.getWidth());
|
|
int nHeight = (int) Math.rint(scalefactor * sourceImage.getHeight());
|
|
Image scaledImage = new Image(url.toURI().toString(), nWidth, nHeight, false, true); // generate a scaled image
|
|
|
|
smmdbImageView.setFitWidth(scaledImage.getWidth()); // set ImageView width to the image width
|
|
smmdbImageView.setImage(scaledImage); // set imageview to image
|
|
} catch (MalformedURLException | URISyntaxException e) {
|
|
LOGGER.warn("There was either a problem or no image!", e);
|
|
smmdbImageView.setImage(new Image("icons/close_black_2048x2048.png"));
|
|
}
|
|
addCourseDescription(courses.get(i));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
helpLbl.setOnMouseClicked(event -> {
|
|
if (event.getButton().equals(MouseButton.PRIMARY)) {
|
|
Main.getMain().getHostServices().showDocument("https://git.mosad.xyz/Seil0/cemu_UI/issues/3");
|
|
}
|
|
});
|
|
|
|
languageChoisBox.getSelectionModel().selectedIndexProperty().addListener((event, oldValue, newValue) -> {
|
|
String language = languageChoisBox.getItems().get((int) newValue).toString();
|
|
language = language.substring(language.length() - 6, language.length() - 1); // reading only en_US from
|
|
// English (en_US)
|
|
XMLController.setUsrLocal(language);
|
|
setUILanguage();
|
|
xmlController.saveSettings();
|
|
});
|
|
|
|
branchChoisBox.getSelectionModel().selectedIndexProperty().addListener((e, oldValue, newValue) -> {
|
|
if (branchChoisBox.getItems().get((int) newValue).toString() == "beta") {
|
|
XMLController.setUseBeta(true);
|
|
} else {
|
|
XMLController.setUseBeta(false);
|
|
}
|
|
xmlController.saveSettings();
|
|
});
|
|
|
|
licensesLbl.setOnMouseClicked(event -> {
|
|
if (event.getButton().equals(MouseButton.PRIMARY)) {
|
|
|
|
EventHandler<ActionEvent> cancelAction = cE -> {
|
|
String textAreaText = "";
|
|
|
|
try {
|
|
BufferedReader licenseBR = new BufferedReader(
|
|
new InputStreamReader(getClass().getResourceAsStream("/licenses/licenses_show.txt")));
|
|
String currentLine;
|
|
|
|
while ((currentLine = licenseBR.readLine()) != null) {
|
|
textAreaText = textAreaText + currentLine + "\n";
|
|
}
|
|
|
|
licenseBR.close();
|
|
} catch (IOException ex) {
|
|
LOGGER.error("Cloud not read the license file!", ex);
|
|
}
|
|
|
|
JFXTextAreaAlert licenseAlert = new JFXTextAreaAlert("cemu_UI", textAreaText, btnStyle, primaryStage);
|
|
licenseAlert.showAndWait();
|
|
};
|
|
|
|
JFXOkayCancelAlert licenseOverviewAlert = new JFXOkayCancelAlert(
|
|
XMLController.getLocalBundle().getString("licensesLblHeadingText"),
|
|
XMLController.getLocalBundle().getString("licensesLblBodyText"), btnStyle, primaryStage);
|
|
licenseOverviewAlert.setOkayAction(oE -> {});
|
|
licenseOverviewAlert.setCancelAction(cancelAction);
|
|
licenseOverviewAlert.setCancelText(XMLController.getLocalBundle().getString("showLicenses"));
|
|
licenseOverviewAlert.showAndWait();
|
|
}
|
|
});
|
|
|
|
cemuTextField.textProperty().addListener((e, oldValue, newValue) -> {
|
|
if (new File(newValue).exists()) {
|
|
XMLController.setCemuPath(newValue);
|
|
xmlController.saveSettings();
|
|
} else {
|
|
String bodyText = newValue + ": No such file or directory";
|
|
JFXInfoAlert fileErrorDialog = new JFXInfoAlert("Waring!", bodyText, btnStyle, primaryStage);
|
|
fileErrorDialog.showAndWait();
|
|
LOGGER.warn(newValue + ": No such file or directory");
|
|
}
|
|
});
|
|
|
|
romTextField.textProperty().addListener((e, oldValue, newValue) -> {
|
|
if (new File(newValue).exists()) {
|
|
XMLController.setRomDirectoryPath(newValue);
|
|
xmlController.saveSettings();
|
|
reloadRoms();
|
|
} else {
|
|
String bodyText = newValue + ": No such file or directory";
|
|
JFXInfoAlert fileErrorDialog = new JFXInfoAlert("Waring!", bodyText, btnStyle, primaryStage);
|
|
fileErrorDialog.showAndWait();
|
|
LOGGER.warn(newValue + ": No such file or directory");
|
|
}
|
|
});
|
|
|
|
LOGGER.info("initializing Actions done!");
|
|
}
|
|
|
|
@FXML
|
|
private void detailsSlideoutBtnAction() {
|
|
playBtnSlideOut();
|
|
}
|
|
|
|
@FXML
|
|
private void aboutBtnAction() {
|
|
String bodyText = "cemu_UI by @Seil0 \nVersion: " + version + " (" + buildNumber + ") \"" + versionName
|
|
+ "\" \n" + XMLController.getLocalBundle().getString("aboutBtnBodyText");
|
|
|
|
JFXInfoAlert infoAlert = new JFXInfoAlert(XMLController.getLocalBundle().getString("aboutBtnHeadingText"),
|
|
bodyText, btnStyle, primaryStage);
|
|
infoAlert.showAndWait();
|
|
}
|
|
|
|
@FXML
|
|
private void settingsBtnAction() {
|
|
if (smmdbAnchorPane.isVisible()) {
|
|
smmdbAnchorPane.setVisible(false);
|
|
}
|
|
settingsScrollPane.setVisible(!settingsScrollPane.isVisible());
|
|
xmlController.saveSettings(); // saving settings to be sure
|
|
}
|
|
|
|
@FXML
|
|
private void reloadRomsBtnAction() throws IOException {
|
|
reloadRoms();
|
|
}
|
|
|
|
@FXML
|
|
private void smmdbBtnAction() {
|
|
// show smmdbAnchorPane
|
|
smmdbAnchorPane.setVisible(!smmdbAnchorPane.isVisible());
|
|
|
|
if (smmdbAnchorPane.isVisible()) {
|
|
// start query in new thread
|
|
Thread thread = new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Platform.runLater(() -> {
|
|
smmdbDownloadBtn.setText(XMLController.getLocalBundle().getString("smmdbDownloadBtnLoading"));
|
|
smmdbDownloadBtn.setDisable(true);
|
|
root.getChildren().remove(0,root.getChildren().size());
|
|
});
|
|
courses.removeAll(courses); // remove existing courses
|
|
courses.addAll(smmdbAPIController.startQuery()); // start query
|
|
|
|
// add query response to courseTreeTable
|
|
for (int i = 0; i < courses.size(); i++) {
|
|
CourseTableDataType helpCourse = new CourseTableDataType(courses.get(i).getTitle(),
|
|
courses.get(i).getId(), courses.get(i).getTime(), courses.get(i).getStars());
|
|
|
|
Platform.runLater(() -> {
|
|
root.getChildren().add(new TreeItem<CourseTableDataType>(helpCourse)); // add data to root-node
|
|
smmdbDownloadBtn.setText(XMLController.getLocalBundle().getString("smmdbDownloadBtnDownload"));
|
|
smmdbDownloadBtn.setDisable(false);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
thread.start();
|
|
}
|
|
}
|
|
|
|
@FXML
|
|
private void playBtnAction() throws InterruptedException, IOException {
|
|
dbController.setLastPlayed(selectedGameTitleID);
|
|
playGame = new playGame(this, dbController);
|
|
|
|
playGame.start();
|
|
}
|
|
|
|
@FXML
|
|
private void totalPlaytimeBtnAction() {
|
|
|
|
}
|
|
|
|
@FXML
|
|
private void lastTimePlayedBtnAction() {
|
|
|
|
}
|
|
|
|
@FXML
|
|
private void cemuTFBtnAction() {
|
|
File cemuDirectory = directoryChooser.showDialog(primaryStage);
|
|
if (cemuDirectory != null) {
|
|
cemuTextField.setText(cemuDirectory.getAbsolutePath());
|
|
}
|
|
}
|
|
|
|
@FXML
|
|
private void romTFBtnAction() {
|
|
File romDirectory = directoryChooser.showDialog(primaryStage);
|
|
if (romDirectory != null) {
|
|
romTextField.setText(romDirectory.getAbsolutePath());
|
|
}
|
|
}
|
|
|
|
@FXML
|
|
private void updateBtnAction() {
|
|
updateController = new UpdateController(this, buildNumber, XMLController.isUseBeta());
|
|
Thread updateThread = new Thread(updateController);
|
|
updateThread.setName("Updater");
|
|
updateThread.start();
|
|
}
|
|
|
|
@FXML
|
|
private void autoUpdateToggleBtnAction() {
|
|
XMLController.setAutoUpdate(!XMLController.isAutoUpdate());
|
|
xmlController.saveSettings();
|
|
}
|
|
|
|
@FXML
|
|
private void courseSearchTextFiledAction() {
|
|
// not in use
|
|
}
|
|
|
|
@FXML
|
|
private void smmdbDownloadBtnAction() {
|
|
String downloadUrl = "http://smmdb.ddns.net/api/downloadcourse?id=" + id + "&type=zip";
|
|
String downloadFileURL = XMLController.getCemuPath() + "/" + id + ".zip"; // getCemuPath() + "/" + smmID + "/" + id + ".rar"
|
|
String outputFile = XMLController.getCemuPath() + "/";
|
|
|
|
try {
|
|
LOGGER.info("beginning download ...");
|
|
HttpURLConnection conn = (HttpURLConnection) new URL(downloadUrl).openConnection();
|
|
ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(null, "Downloading...", conn.getInputStream());
|
|
ProgressMonitor pm = pmis.getProgressMonitor();
|
|
pm.setMillisToDecideToPopup(0);
|
|
pm.setMillisToPopup(0);
|
|
pm.setMinimum(0); // tell the progress bar that we start at the beginning of the stream
|
|
pm.setMaximum(conn.getContentLength()); // tell the progress bar the total number of bytes we are going to read.
|
|
FileUtils.copyInputStreamToFile(pmis, new File(downloadFileURL)); // download file + "/mlc01/emulatorSave"
|
|
pmis.close();
|
|
LOGGER.info("downloaded successfull");
|
|
|
|
File downloadFile = new File(downloadFileURL);
|
|
|
|
String source = downloadFileURL;
|
|
String destination = null;
|
|
int highestCourseNumber = 0;
|
|
String courseName = null;
|
|
|
|
for (int i = 0; i < smmIDs.size(); i++) {
|
|
File smmDirectory = new File(outputFile + "mlc01/emulatorSave/" + smmIDs.get(i));
|
|
|
|
if (smmDirectory.exists()) {
|
|
LOGGER.info("found smm directory: " + smmDirectory.getAbsolutePath());
|
|
File[] courses = smmDirectory.listFiles(File::isDirectory);
|
|
|
|
// get all existing courses in smm directory, new name is highest number +1
|
|
for (int j = 0; j < courses.length; j++) {
|
|
int courseNumber = Integer.parseInt(courses[j].getName().substring(6));
|
|
if (courseNumber > highestCourseNumber) {
|
|
highestCourseNumber = courseNumber;
|
|
}
|
|
}
|
|
|
|
String number = "000" + (highestCourseNumber +1);
|
|
courseName = "course" + number.substring(number.length() -3, number.length());
|
|
File courseDirectory = new File(outputFile + "mlc01/emulatorSave/" + smmIDs.get(i) + "/");
|
|
destination = courseDirectory.getPath();
|
|
}
|
|
}
|
|
|
|
if (destination != null) {
|
|
try {
|
|
ZipFile zipFile = new ZipFile(source);
|
|
zipFile.extractAll(destination);
|
|
|
|
// rename zip-file
|
|
File course = new File(destination + "/course000");
|
|
course.renameTo( new File(destination + "/" + courseName));
|
|
LOGGER.info("Added new course: " + courseName + ", full path is: " + destination + "/" + courseName);
|
|
} catch (ZipException e) {
|
|
LOGGER.error("an error occurred during unziping the file!", e);
|
|
}
|
|
}
|
|
|
|
downloadFile.delete();
|
|
} catch (IOException e) {
|
|
LOGGER.error("something went wrong during downloading the course", e);
|
|
}
|
|
}
|
|
|
|
@FXML
|
|
private void fullscreenToggleBtnAction() {
|
|
XMLController.setFullscreen(!XMLController.isFullscreen());
|
|
xmlController.saveSettings();
|
|
}
|
|
|
|
@FXML
|
|
private void cloudSyncToggleBtnAction() {
|
|
XMLController.setCloudSync(!XMLController.isCloudSync());
|
|
|
|
if (XMLController.isCloudSync()) {
|
|
EventHandler<ActionEvent> okayAction = e -> {
|
|
// TODO rework for other cloud services
|
|
// CloudService service = CloudService.GoogleDrive;
|
|
XMLController.setCloudService(CloudService.GoogleDrive);
|
|
|
|
// start cloud sync in new thread
|
|
Thread thread = new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
|
|
if (main.getCloudController().initializeConnection(XMLController.getCloudService(),
|
|
XMLController.getCemuPath())) {
|
|
main.getCloudController().sync(XMLController.getCloudService(), XMLController.getCemuPath(),
|
|
XMLController.getDirCemuUIPath());
|
|
xmlController.saveSettings();
|
|
} else {
|
|
cloudSyncToggleBtn.setSelected(false);
|
|
|
|
// cloud sync init error dialog
|
|
JFXInfoAlert cloudSyncErrorDialog = new JFXInfoAlert(
|
|
XMLController.getLocalBundle().getString("cloudSyncErrorHeadingText"),
|
|
XMLController.getLocalBundle().getString("cloudSyncErrorBodyText"), btnStyle, primaryStage);
|
|
cloudSyncErrorDialog.showAndWait();
|
|
}
|
|
|
|
}
|
|
});
|
|
thread.start();
|
|
};
|
|
|
|
JFXOkayCancelAlert cloudSyncWarningAlert = new JFXOkayCancelAlert(
|
|
XMLController.getLocalBundle().getString("cloudSyncWaringHeadingText"),
|
|
XMLController.getLocalBundle().getString("cloudSyncWaringHeadingText"), btnStyle, primaryStage);
|
|
cloudSyncWarningAlert.setOkayAction(okayAction);
|
|
cloudSyncWarningAlert.setCancelAction(e -> cloudSyncToggleBtn.setSelected(false));
|
|
cloudSyncWarningAlert.showAndWait();
|
|
}
|
|
}
|
|
|
|
@FXML
|
|
private void colorPickerAction() {
|
|
editColor(colorPicker.getValue().toString());
|
|
applyColor();
|
|
}
|
|
|
|
@FXML
|
|
private void addBtnAction() {
|
|
JFXEditGameAlert addGameAlert = new JFXEditGameAlert(
|
|
XMLController.getLocalBundle().getString("addGameBtnHeadingText"),
|
|
XMLController.getLocalBundle().getString("addGameBtnBodyText"), btnStyle, 0, primaryStage, MWC);
|
|
addGameAlert.showAndWait();
|
|
}
|
|
|
|
/**
|
|
* process the returning data from the addGame dialog
|
|
* and add them to the database and the UI
|
|
*/
|
|
public void addBtnReturn(String title, String coverPath, String romPath, String titleID) {
|
|
/**
|
|
* if one parameter dosen't contain any value do not add the game
|
|
* else convert the cover to .png add copy it into the picture cache,
|
|
* then add the rom to the local_roms database
|
|
*/
|
|
if (romPath.length() == 0 || coverPath.length() == 0 || title.length() == 0 || titleID.length() == 0) {
|
|
LOGGER.info("No parameter set!");
|
|
|
|
// addGame error dialog
|
|
JFXInfoAlert errorAlert = new JFXInfoAlert(
|
|
XMLController.getLocalBundle().getString("addBtnReturnErrorHeadingText"),
|
|
XMLController.getLocalBundle().getString("addBtnReturnErrorBodyText"), btnStyle, primaryStage);
|
|
errorAlert.showAndWait();
|
|
|
|
} else {
|
|
File pictureCache = XMLController.getPictureCache();
|
|
String coverName = new File(coverPath).getName();
|
|
try {
|
|
BufferedImage originalImage = ImageIO.read(new File(coverPath)); //load cover
|
|
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
|
|
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 400, 600);
|
|
coverPath = pictureCache + "/" + coverName;
|
|
ImageIO.write(resizeImagePNG, "png", new File(coverPath)); //save image to pictureCache
|
|
} catch (IOException e) {
|
|
LOGGER.error("Ops something went wrong! Error while resizing cover.", e);
|
|
}
|
|
|
|
try {
|
|
dbController.addGame(title, coverPath, romPath, titleID, "", "", "", "0");
|
|
games.add(dbController.loadSingleGame(titleID));
|
|
addGame(games.stream().filter(x -> x.getRomPath().equals(romPath)).findFirst().orElse(null));
|
|
if (menuTrue) {
|
|
sideMenuSlideOut();
|
|
burgerTask.setRate(-1.0);
|
|
burgerTask.play();
|
|
menuTrue = false;
|
|
}
|
|
refreshUIData();
|
|
} catch (SQLException e) {
|
|
LOGGER.error("Oops, something went wrong! Error while adding a game.", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void editBtnReturn(String title, String coverPath, String romPath, String titleID) {
|
|
dbController.setGameInfo(title, coverPath, romPath, titleID);
|
|
games.remove(selectedUIDataIndex);
|
|
games.add(dbController.loadSingleGame(titleID));
|
|
addGame(games.stream().filter(x -> x.getRomPath().equals(romPath)).findFirst().orElse(null));
|
|
refreshUIData();
|
|
|
|
LOGGER.info("successfully edited " + titleID + ", new name is \"" + title + "\"");
|
|
}
|
|
|
|
/**
|
|
* add the context menu and button action for all games
|
|
*/
|
|
private void addAllGames() {
|
|
for (UIROMDataType game : games) {
|
|
addGame(game);
|
|
}
|
|
|
|
refreshUIData(); // refresh the list of games displayed on screen
|
|
}
|
|
|
|
/**
|
|
* add the context menu and button action for one game
|
|
* @param game a game
|
|
*/
|
|
private void addGame(UIROMDataType game) {
|
|
game.getButton().setContextMenu(gameContextMenu);
|
|
game.getButton().addEventHandler(MouseEvent.MOUSE_CLICKED, (event) -> {
|
|
LOGGER.info("selected: " + game.getLabel().getText() + "; ID: " + game.getTitleID());
|
|
// getting the selected game index by comparing event.getSource() with games.get(i).getButton()
|
|
for (int i = 0; i < games.size(); i++) {
|
|
if (games.get(i).getButton() == event.getSource()) {
|
|
selectedUIDataIndex = i;
|
|
}
|
|
}
|
|
|
|
gameExecutePath = game.getRomPath();
|
|
selectedGameTitleID = game.getTitleID();
|
|
selectedGameTitle = game.getName();
|
|
|
|
// underlining selected Label
|
|
lastGameLabel.setStyle("-fx-underline: false;");
|
|
games.get(selectedUIDataIndex).getLabel().setStyle("-fx-underline: true;");
|
|
lastGameLabel = games.get(selectedUIDataIndex).getLabel();
|
|
|
|
// setting last played, if lastPlayed is empty game was never played before, else set correct date
|
|
if (dbController.getLastPlayed(game.getTitleID()).equals("") || dbController.getLastPlayed(game.getTitleID()).equals(null)) {
|
|
lastTimePlayedBtn.setText(lastPlayed + never);
|
|
totalPlaytimeBtn.setText(dbController.getTotalPlaytime(game.getTitleID()) + " min");
|
|
} else {
|
|
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
|
int tToday = Integer.parseInt(dtf.format(LocalDate.now()).replaceAll("-", ""));
|
|
int tYesterday = Integer.parseInt(dtf.format(LocalDate.now().minusDays(1)).replaceAll("-", ""));
|
|
int tLastPlayedDay = Integer.parseInt(dbController.getLastPlayed(game.getTitleID()).replaceAll("-", ""));
|
|
|
|
if (tLastPlayedDay == tToday) {
|
|
lastTimePlayedBtn.setText(lastPlayed + today);
|
|
} else if (tLastPlayedDay == tYesterday) {
|
|
lastTimePlayedBtn.setText(lastPlayed + yesterday);
|
|
} else {
|
|
lastTimePlayedBtn.setText(lastPlayed + dbController.getLastPlayed(game.getTitleID()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* setting total playtime, if total playtime > 60 minutes, format is "x hours x
|
|
* minutes" (x h x min), else only minutes are showed
|
|
*/
|
|
if (Integer.parseInt(dbController.getTotalPlaytime(game.getTitleID())) > 60) {
|
|
int hoursPlayed = (int) Math.floor(Integer.parseInt(dbController.getTotalPlaytime(game.getTitleID())) / 60);
|
|
int minutesPlayed = Integer.parseInt(dbController.getTotalPlaytime(game.getTitleID())) - 60 * hoursPlayed;
|
|
totalPlaytimeBtn.setText(hoursPlayed + " h " + minutesPlayed + " min");
|
|
} else {
|
|
totalPlaytimeBtn.setText(dbController.getTotalPlaytime(game.getTitleID()) + " min");
|
|
}
|
|
|
|
if (!playTrue) {
|
|
playBtnSlideIn();
|
|
}
|
|
if (menuTrue) {
|
|
sideMenuSlideOut();
|
|
burgerTask.setRate(-1.0);
|
|
burgerTask.play();
|
|
menuTrue = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* reload all ROMs from the ROM directory
|
|
*/
|
|
public void reloadRoms() {
|
|
JFXSpinner spinner = new JFXSpinner();
|
|
spinner.setPrefSize(30, 30);
|
|
AnchorPane.setTopAnchor(spinner, (mainAnchorPane.getPrefHeight() - spinner.getPrefHeight()) / 2);
|
|
AnchorPane.setLeftAnchor(spinner, (mainAnchorPane.getPrefWidth() - spinner.getPrefWidth()) / 2);
|
|
|
|
Runnable task = () -> {
|
|
Platform.runLater(() -> {
|
|
gamesFlowPane.getChildren().clear(); //remove all games form gamesFlowPane
|
|
mainAnchorPane.getChildren().add(spinner); // add spinner to mainAnchorPane
|
|
});
|
|
|
|
dbController.loadRomDirectory(XMLController.getRomDirectoryPath()); // reload the ROM directory
|
|
games.clear(); // remove all games from the mwc game list
|
|
games = dbController.loadAllGames();
|
|
addAllGames();
|
|
|
|
Platform.runLater(() -> {
|
|
mainAnchorPane.getChildren().remove(spinner);
|
|
});
|
|
};
|
|
|
|
new Thread(task).start();
|
|
}
|
|
|
|
// remove all games from gamesFlowPane and add them afterwards
|
|
public void refreshUIData() {
|
|
gamesFlowPane.getChildren().clear();
|
|
gamesFlowPane.getChildren().addAll(games);
|
|
}
|
|
|
|
// set the selected local strings to all needed elements
|
|
void setUILanguage(){
|
|
switch (XMLController.getUsrLocal()) {
|
|
case "en_US":
|
|
XMLController.setLocalBundle(ResourceBundle.getBundle("locals.cemu_UI-Local", Locale.US)); // us_English
|
|
languageChoisBox.getSelectionModel().select(0);
|
|
break;
|
|
case "de_DE":
|
|
XMLController.setLocalBundle(ResourceBundle.getBundle("locals.cemu_UI-Local", Locale.GERMAN)); // German
|
|
languageChoisBox.getSelectionModel().select(1);
|
|
break;
|
|
default:
|
|
XMLController.setLocalBundle(ResourceBundle.getBundle("locals.cemu_UI-Local", Locale.US)); // default local
|
|
languageChoisBox.getSelectionModel().select(0);
|
|
break;
|
|
}
|
|
|
|
// Buttons
|
|
aboutBtn.setText(XMLController.getLocalBundle().getString("aboutBtn"));
|
|
settingsBtn.setText(XMLController.getLocalBundle().getString("settingsBtn"));
|
|
addBtn.setText(XMLController.getLocalBundle().getString("addBtn"));
|
|
reloadRomsBtn.setText(XMLController.getLocalBundle().getString("reloadRomsBtn"));
|
|
smmdbBtn.setText(XMLController.getLocalBundle().getString("smmdbBtn"));
|
|
cemuTFBtn.setText(XMLController.getLocalBundle().getString("cemuTFBtn"));
|
|
romTFBtn.setText(XMLController.getLocalBundle().getString("romTFBtn"));
|
|
updateBtn.setText(XMLController.getLocalBundle().getString("updateBtnCheckNow"));
|
|
smmdbDownloadBtn.setText(XMLController.getLocalBundle().getString("smmdbDownloadBtn"));
|
|
playBtn.setText(XMLController.getLocalBundle().getString("playBtn"));
|
|
cloudSyncToggleBtn.setText(XMLController.getLocalBundle().getString("cloudSyncToggleBtn"));
|
|
autoUpdateToggleBtn.setText(XMLController.getLocalBundle().getString("autoUpdateToggleBtn"));
|
|
fullscreenToggleBtn.setText(XMLController.getLocalBundle().getString("fullscreenToggleBtn"));
|
|
|
|
// Labels
|
|
cemu_UISettingsLbl.setText(XMLController.getLocalBundle().getString("cemu_UISettingsLbl"));
|
|
cemuDirectoryLbl.setText(XMLController.getLocalBundle().getString("cemuDirectoryLbl"));
|
|
romDirectoryLbl.setText(XMLController.getLocalBundle().getString("romDirectoryLbl"));
|
|
mainColorLbl.setText(XMLController.getLocalBundle().getString("mainColorLbl"));
|
|
languageLbl.setText(XMLController.getLocalBundle().getString("languageLbl"));
|
|
updateLbl.setText(XMLController.getLocalBundle().getString("updateLbl"));
|
|
branchLbl.setText(XMLController.getLocalBundle().getString("branchLbl"));
|
|
cemuSettingsLbl.setText(XMLController.getLocalBundle().getString("cemuSettingsLbl"));
|
|
licensesLbl.setText(XMLController.getLocalBundle().getString("licensesLbl"));
|
|
|
|
// Columns
|
|
titleColumn.setText(XMLController.getLocalBundle().getString("titleColumn"));
|
|
idColumn.setText(XMLController.getLocalBundle().getString("idColumn"));
|
|
starsColumn.setText(XMLController.getLocalBundle().getString("starsColumn"));
|
|
timeColumn.setText(XMLController.getLocalBundle().getString("timeColumn"));
|
|
|
|
// Strings
|
|
lastPlayed = XMLController.getLocalBundle().getString("lastPlayed");
|
|
today = XMLController.getLocalBundle().getString("today");
|
|
yesterday = XMLController.getLocalBundle().getString("yesterday");
|
|
never = XMLController.getLocalBundle().getString("never");
|
|
}
|
|
|
|
// if AutoUpdate, then check for updates
|
|
private void checkAutoUpdate() {
|
|
|
|
if (XMLController.isAutoUpdate()) {
|
|
try {
|
|
LOGGER.info("AutoUpdate: looking for updates on startup ...");
|
|
updateController = new UpdateController(this, buildNumber, XMLController.isUseBeta());
|
|
Thread updateThread = new Thread(updateController);
|
|
updateThread.setName("Updater");
|
|
updateThread.start();
|
|
updateThread.join();
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void addCourseDescription(SmmdbApiDataType course) {
|
|
String courseTheme;
|
|
String gameStyle;
|
|
String difficulty;
|
|
String autoscroll;
|
|
smmdbTextFlow.getChildren().remove(0, smmdbTextFlow.getChildren().size());
|
|
nameText.clear();
|
|
courseText.clear();
|
|
|
|
switch (course.getCourseTheme()) {
|
|
case 0:
|
|
courseTheme = "Ground";
|
|
break;
|
|
case 1:
|
|
courseTheme = "Underground";
|
|
break;
|
|
case 2:
|
|
courseTheme = "Castle";
|
|
break;
|
|
case 3:
|
|
courseTheme = "Airship";
|
|
break;
|
|
case 4:
|
|
courseTheme = "Underwater";
|
|
break;
|
|
case 5:
|
|
courseTheme = "Ghost House";
|
|
break;
|
|
default:
|
|
courseTheme = "notset";
|
|
break;
|
|
}
|
|
|
|
switch (course.getGameStyle()) {
|
|
case 0:
|
|
gameStyle = "SMB";
|
|
break;
|
|
case 1:
|
|
gameStyle = "SMB3";
|
|
break;
|
|
case 2:
|
|
gameStyle = "SMW";
|
|
break;
|
|
case 3:
|
|
gameStyle = "NSMBU";
|
|
break;
|
|
default:
|
|
gameStyle = "notset";
|
|
break;
|
|
}
|
|
|
|
switch (course.getDifficulty()) {
|
|
case 0:
|
|
difficulty = "Easy";
|
|
break;
|
|
case 1:
|
|
difficulty = "Normal";
|
|
break;
|
|
case 2:
|
|
difficulty = "Expert";
|
|
break;
|
|
case 3:
|
|
difficulty = "Super Expert";
|
|
break;
|
|
case 4:
|
|
difficulty = "Mixed";
|
|
break;
|
|
default:
|
|
difficulty = "notset";
|
|
break;
|
|
}
|
|
|
|
switch (course.getAutoScroll()) {
|
|
case 0:
|
|
autoscroll = "disabled";
|
|
break;
|
|
case 1:
|
|
autoscroll = "slow";
|
|
break;
|
|
case 2:
|
|
autoscroll = "medium";
|
|
break;
|
|
case 3:
|
|
autoscroll = "fast";
|
|
break;
|
|
default:
|
|
autoscroll = "notset";
|
|
break;
|
|
}
|
|
|
|
nameText.add(0, new Text("title" + ": "));
|
|
nameText.add(1, new Text("owner" + ": "));
|
|
nameText.add(2, new Text("Course-Theme" + ": "));
|
|
nameText.add(3, new Text("Game-Style" + ": "));
|
|
nameText.add(4, new Text("difficulty" + ": "));
|
|
nameText.add(5, new Text("Auto-Scroll" + ": "));
|
|
nameText.add(6, new Text("Time" + ": "));
|
|
nameText.add(7, new Text("lastmodified" + ": "));
|
|
nameText.add(8, new Text("uploaded" + ": "));
|
|
nameText.add(9, new Text("nintendoid" + ": "));
|
|
|
|
courseText.add(0, new Text(course.getTitle() + "\n"));
|
|
courseText.add(1, new Text(course.getOwner() + "\n"));
|
|
courseText.add(2, new Text(courseTheme + "\n"));
|
|
courseText.add(3, new Text(gameStyle + "\n"));
|
|
courseText.add(4, new Text(difficulty + "\n"));
|
|
courseText.add(5, new Text(autoscroll + "\n"));
|
|
courseText.add(6, new Text(course.getTime() + "\n"));
|
|
courseText.add(7, new Text(new java.util.Date((long) course.getLastmodified() * 1000) + "\n"));
|
|
courseText.add(8, new Text(new java.util.Date((long) course.getUploaded() * 1000) + "\n"));
|
|
courseText.add(9, new Text(course.getNintendoid() + "\n"));
|
|
|
|
for (int i = 0; i < nameText.size(); i++) {
|
|
nameText.get(i).setFont(Font.font("System", FontWeight.BOLD, 14));
|
|
courseText.get(i).setFont(Font.font("System", 14));
|
|
smmdbTextFlow.getChildren().addAll(nameText.get(i), courseText.get(i));
|
|
}
|
|
|
|
}
|
|
|
|
// change the color of all needed GUI elements
|
|
private void applyColor() {
|
|
String boxStyle = "-fx-background-color: #" + XMLController.getColor() + ";";
|
|
String textFill = "";
|
|
BigInteger icolor = new BigInteger(XMLController.getColor(),16);
|
|
BigInteger ccolor = new BigInteger("78909cff",16);
|
|
|
|
sideMenuVBox.setStyle(boxStyle);
|
|
topHBox.setStyle(boxStyle);
|
|
cemuTextField.setFocusColor(Color.valueOf(XMLController.getColor()));
|
|
romTextField.setFocusColor(Color.valueOf(XMLController.getColor()));
|
|
|
|
if (icolor.compareTo(ccolor) == -1) {
|
|
textFill = "-fx-text-fill: WHITE;";
|
|
|
|
aboutBtn.setGraphic(new ImageView(new Image("icons/ic_info_white_24dp_1x.png")));
|
|
settingsBtn.setGraphic(new ImageView(new Image("icons/ic_settings_white_24dp_1x.png")));
|
|
addBtn.setGraphic(new ImageView(new Image("icons/ic_add_circle_white_24dp_1x.png")));
|
|
reloadRomsBtn.setGraphic(new ImageView(new Image("icons/ic_cached_white_24dp_1x.png")));
|
|
smmdbBtn.setGraphic(new ImageView(new Image("icons/ic_get_app_white_24dp_1x.png")));
|
|
|
|
menuHam.getStyleClass().clear();
|
|
menuHam.getStyleClass().add("jfx-hamburgerW");
|
|
} else {
|
|
textFill = "-fx-text-fill: BLACK;";
|
|
|
|
aboutBtn.setGraphic(new ImageView(new Image("icons/ic_info_black_24dp_1x.png")));
|
|
settingsBtn.setGraphic(new ImageView(new Image("icons/ic_settings_black_24dp_1x.png")));
|
|
addBtn.setGraphic(new ImageView(new Image("icons/ic_add_circle_black_24dp_1x.png")));
|
|
reloadRomsBtn.setGraphic(new ImageView(new Image("icons/ic_cached_black_24dp_1x.png")));
|
|
smmdbBtn.setGraphic(new ImageView(new Image("icons/ic_get_app_black_24dp_1x.png")));
|
|
|
|
menuHam.getStyleClass().clear();
|
|
menuHam.getStyleClass().add("jfx-hamburgerB");
|
|
}
|
|
|
|
btnStyle = "-fx-button-type: RAISED; -fx-background-color: #" + XMLController.getColor() + "; " + textFill;
|
|
|
|
aboutBtn.setStyle(textFill);
|
|
settingsBtn.setStyle(textFill);
|
|
addBtn.setStyle(textFill);
|
|
reloadRomsBtn.setStyle(textFill);
|
|
smmdbBtn.setStyle(textFill);
|
|
playBtn.setStyle(textFill);
|
|
cemuTFBtn.setStyle(btnStyle);
|
|
romTFBtn.setStyle(btnStyle);
|
|
updateBtn.setStyle(btnStyle);
|
|
smmdbDownloadBtn.setStyle(btnStyle);
|
|
playBtn.setStyle(btnStyle);
|
|
|
|
for(UIROMDataType game : games) {
|
|
game.getButton().setRipplerFill(Paint.valueOf(XMLController.getColor()));
|
|
}
|
|
}
|
|
|
|
private void sideMenuSlideIn(){
|
|
sideMenuVBox.setVisible(true);
|
|
//slide in in 400ms
|
|
TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox);
|
|
translateTransition.setFromX(-175);
|
|
translateTransition.setToX(0);
|
|
translateTransition.play();
|
|
}
|
|
|
|
private void sideMenuSlideOut(){
|
|
//slide out in 400ms
|
|
TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox);
|
|
translateTransition.setFromX(0);
|
|
translateTransition.setToX(-175);
|
|
translateTransition.play();
|
|
}
|
|
|
|
private void playBtnSlideIn(){
|
|
bottomHBox.setVisible(true);
|
|
playTrue = true;
|
|
|
|
TranslateTransition playBtnTransition = new TranslateTransition(Duration.millis(300), bottomHBox);
|
|
playBtnTransition.setFromY(56);
|
|
playBtnTransition.setToY(0);
|
|
playBtnTransition.play();
|
|
}
|
|
|
|
private void playBtnSlideOut(){
|
|
playTrue = false;
|
|
TranslateTransition playBtnTransition = new TranslateTransition(Duration.millis(300), bottomHBox);
|
|
playBtnTransition.setFromY(0);
|
|
playBtnTransition.setToY(56);
|
|
playBtnTransition.play();
|
|
}
|
|
|
|
private void editColor(String input){
|
|
StringBuilder sb = new StringBuilder(input);
|
|
sb.delete(0, 2);
|
|
XMLController.setColor(sb.toString());
|
|
xmlController.saveSettings();
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
/**
|
|
* @return the main color in hexadecimal format
|
|
*/
|
|
private String hexToRgb() {
|
|
LOGGER.info(XMLController.getColor());
|
|
int hex = Integer.parseInt(XMLController.getColor().substring(0, 5), 16);
|
|
|
|
int r = (hex & 0xFF0000) >> 16;
|
|
int g = (hex & 0xFF00) >> 8;
|
|
int b = (hex & 0xFF);
|
|
|
|
return r + ", " + g + ", " + b;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param originalImage original image which size is changed
|
|
* @param type type of the original image (PNG,JPEG,...)
|
|
* @param imgWidth wanted width
|
|
* @param imgHeigth wanted height
|
|
* @return the rezised image
|
|
*/
|
|
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int imgWidth, int imgHeigth) {
|
|
BufferedImage resizedImage = new BufferedImage(imgWidth, imgHeigth, type);
|
|
Graphics2D g = resizedImage.createGraphics();
|
|
g.drawImage(originalImage, 0, 0, imgWidth, imgHeigth, null);
|
|
g.dispose();
|
|
|
|
return resizedImage;
|
|
}
|
|
|
|
public Main getMain() {
|
|
return main;
|
|
}
|
|
|
|
public Stage getPrimaryStage() {
|
|
return primaryStage;
|
|
}
|
|
|
|
public String getGameExecutePath() {
|
|
return gameExecutePath;
|
|
}
|
|
|
|
public void setGameExecutePath(String gameExecutePath) {
|
|
this.gameExecutePath = gameExecutePath;
|
|
}
|
|
|
|
public String getSelectedGameTitleID() {
|
|
return selectedGameTitleID;
|
|
}
|
|
|
|
public void setSelectedGameTitleID(String selectedGameTitleID) {
|
|
this.selectedGameTitleID = selectedGameTitleID;
|
|
}
|
|
|
|
public JFXButton getPlayBtn() {
|
|
return playBtn;
|
|
}
|
|
|
|
public void setPlayBtn(JFXButton playBtn) {
|
|
this.playBtn = playBtn;
|
|
}
|
|
|
|
public AnchorPane getMainAnchorPane() {
|
|
return mainAnchorPane;
|
|
}
|
|
|
|
public JFXButton getUpdateBtn() {
|
|
return updateBtn;
|
|
}
|
|
|
|
}
|