/** * cemu_UI * * Copyright 2017 <@Seil0> * * "THE CHOCOLATE-WARE LICENSE" (Revision 1): * As long as you retain this notice this software is licensed under the GNU GENERAL PUBLIC LICENSE Version 3, * with the following additions: * If we meet some day, and you think this stuff is worth it, * you can buy me a chocolate in return. - @Seil0 * (license based in Beer-ware, see https://fedoraproject.org/wiki/Licensing/Beerware ) * */ package application; import java.awt.Desktop; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URI; 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.Optional; import java.util.Properties; 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.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXColorPicker; import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.controls.JFXHamburger; 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 datatypes.CourseTableDataType; import datatypes.SmmdbApiDataType; import datatypes.UIROMDataType; import javafx.animation.FadeTransition; import javafx.animation.ParallelTransition; import javafx.animation.TranslateTransition; 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.geometry.Insets; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonType; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; import javafx.scene.control.TextInputDialog; 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.HBox; import javafx.scene.layout.StackPane; 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.FileChooser; 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 smmdbDownloadBtn; @FXML private JFXButton playBtn; @FXML private JFXButton lastTimePlayedBtn; @FXML JFXButton timePlayedBtn; @FXML private JFXHamburger menuHam; @FXML private JFXTextField cemuTextField; @FXML private JFXTextField romTextField; @FXML private TextFlow smmdbTextFlow; @FXML private JFXColorPicker colorPicker; @FXML private JFXToggleButton fullscreenToggleBtn; @FXML private JFXToggleButton cloudSyncToggleBtn; @FXML private AnchorPane settingsAnchorPane; @FXML private AnchorPane smmdbAnchorPane; @FXML private AnchorPane gamesAnchorPane; @FXML private ScrollPane scrollPaneMain; @FXML private ScrollPane smmdbScrollPane; @FXML private VBox sideMenuVBox; @FXML private HBox topHBox; @FXML private ImageView smmdbImageView; @FXML private Label helpLabel; @FXML private JFXTreeTableView courseTreeTable = new JFXTreeTableView(); @FXML TreeItem root = new TreeItem<>(new CourseTableDataType("","",0,0)); @FXML private JFXTreeTableColumn titleColumn = new JFXTreeTableColumn<>("title"); @FXML private JFXTreeTableColumn idColumn = new JFXTreeTableColumn<>("id"); @FXML private JFXTreeTableColumn starsColumn = new JFXTreeTableColumn<>("stars"); @FXML private JFXTreeTableColumn timeColumn = new JFXTreeTableColumn<>("time"); Main main; dbController dbController; SmmdbApiQuery smmdbApiQuery; playGame playGame; private boolean menuTrue = false; private boolean settingsTrue = false; private boolean playTrue = false; private boolean smmdbTrue = false; private boolean fullscreen; private boolean cloudSync; private String cloudService = ""; //set cloud provider (at the moment only GoogleDrive, Dropbox is planed) private String cemuPath; private String romPath; private String gameExecutePath; private String color; private String dialogBtnStyle; private String selectedGameTitleID; private String selectedGameTitle; private String id; private String version = "0.1.6"; private String buildNumber = "037"; private String versionName = "Throwback Galaxy"; private int xPos = -200; private int yPos = 17; private int xPosHelper; private int selectedUIDataIndex; private int selected; private DirectoryChooser directoryChooser = new DirectoryChooser(); private File dirWin = new File(System.getProperty("user.home") + "/Documents/cemu_UI"); private File dirLinux = new File(System.getProperty("user.home") + "/cemu_UI"); private File fileWin = new File(dirWin + "/config.xml"); private File fileLinux = new File(dirLinux + "/config.xml"); File pictureCacheWin = new File(dirWin+"/picture_cache"); File pictureCacheLinux = new File(dirLinux+"/picture_cache"); private ObservableList smmIDs = FXCollections.observableArrayList("fe31b7f2", "44fc5929"); //TODO add more IDs private ObservableList games = FXCollections.observableArrayList(); ObservableList courses = FXCollections.observableArrayList(); ArrayList courseText = new ArrayList(); ArrayList nameText = new ArrayList(); Properties props = new Properties(); Properties gameProps = new Properties(); private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName()); private MenuItem edit = new MenuItem("edit"); private MenuItem remove = new MenuItem("remove"); private MenuItem update = new MenuItem("update"); private MenuItem addDLC = new MenuItem("add DLC"); private ContextMenu gameContextMenu = new ContextMenu(edit, remove, update, addDLC); private Label lastGameLabel = new Label(); private ImageView add_circle_black = new ImageView(new Image("resources/icons/ic_add_circle_black_24dp_1x.png")); private ImageView info_black = new ImageView(new Image("resources/icons/ic_info_black_24dp_1x.png")); private ImageView settings_black = new ImageView(new Image("resources/icons/ic_settings_black_24dp_1x.png")); private ImageView cached_black = new ImageView(new Image("resources/icons/ic_cached_black_24dp_1x.png")); private ImageView smmdb_black = new ImageView(new Image("resources/icons/ic_get_app_black_24dp_1x.png")); private ImageView add_circle_white = new ImageView(new Image("resources/icons/ic_add_circle_white_24dp_1x.png")); private ImageView info_white = new ImageView(new Image("resources/icons/ic_info_white_24dp_1x.png")); private ImageView settings_white = new ImageView(new Image("resources/icons/ic_settings_white_24dp_1x.png")); private ImageView cached_white = new ImageView(new Image("resources/icons/ic_cached_white_24dp_1x.png")); private ImageView smmdb_white = new ImageView(new Image("resources/icons/ic_get_app_white_24dp_1x.png")); private Image close_black = new Image("resources/icons/close_black_2048x2048.png"); public void setMain(Main main) { this.main = main; dbController = new dbController(this); smmdbApiQuery = new SmmdbApiQuery(); } void initUI(){ cemuTextField.setText(cemuPath); romTextField.setText(romPath); colorPicker.setValue(Color.valueOf(getColor())); fullscreenToggleBtn.setSelected(isFullscreen()); cloudSyncToggleBtn.setSelected(isCloudSync()); edit.setDisable(true); applyColor(); //initialize courseTable titleColumn.setPrefWidth(160); timeColumn.setPrefWidth(127); starsColumn.setPrefWidth(100); 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); //hide idColumn (important) } /** * initialize all actions not initialized by a own method */ void initActions() { LOGGER.info("initializing Actions... "); // System.out.println("initializing Actions... "); HamburgerBackArrowBasicTransition 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 (settingsTrue) { settingsAnchorPane.setVisible(false); // setPath(tfPath.getText()); saveSettings(); settingsTrue = false; } if (smmdbTrue) { smmdbAnchorPane.setVisible(false); smmdbTrue = false; } }); edit.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { System.out.println("edit "+selectedGameTitleID); if(selectedGameTitleID == null){ System.out.println("trying to edit null! null is not valid!"); Alert alert = new Alert(AlertType.WARNING); alert.setTitle("edit"); alert.setHeaderText("cemu_UI"); alert.setContentText("please select a game, \""+selectedGameTitleID+"\" is not a valid type"); alert.initOwner(main.primaryStage); alert.showAndWait(); }else{ System.out.println("show edit window TODO!"); //TODO show edit window } } }); remove.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { System.out.println("remove "+selectedGameTitleID); if(selectedGameTitleID == null){ System.out.println("trying to remove null! null is not valid!"); Alert alert = new Alert(AlertType.WARNING); alert.setTitle("remove"); alert.setHeaderText("cemu_UI"); alert.setContentText("please select a game, \""+selectedGameTitleID+"\" is not a valid type"); alert.initOwner(main.primaryStage); alert.showAndWait(); } else{ Alert alert = new Alert(AlertType.CONFIRMATION); alert.setTitle("remove"); alert.setHeaderText("cemu_UI"); alert.setContentText("Are you sure you want to delete "+selectedGameTitle+" ?"); alert.initOwner(main.primaryStage); Optional result = alert.showAndWait(); if (result.get() == ButtonType.OK){ try { //remove all elements from gamesAnchorPane for(int i=0; i< games.size(); i++){ gamesAnchorPane.getChildren().remove(games.get(i).getVBox()); } //remove game from database games.remove(selectedUIDataIndex); dbController.removeRom(selectedGameTitleID); //remove all games form gamesAnchorPane (UI) gamesAnchorPane.getChildren().removeAll(gamesAnchorPane.getChildren()); //reset position xPos = -200; yPos = 17; xPosHelper = 0; //add all games to gamesAnchorPane (UI) for(int i=0; i< games.size(); i++){ generatePosition(); games.get(i).getVBox().setLayoutX(getxPos()); games.get(i).getVBox().setLayoutY(getyPos()); gamesAnchorPane.getChildren().add(games.get(i).getVBox()); } } catch (Exception e) { e.printStackTrace(); } } } } }); update.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { String titleID = selectedGameTitleID; String updatePath; System.out.println("update: "+selectedGameTitleID); if(selectedGameTitleID == null){ System.out.println("trying to update null! null is not valid!"); Alert alert = new Alert(AlertType.WARNING); alert.setTitle("edit"); alert.setHeaderText("cemu_UI"); alert.setContentText("please select a game, \""+selectedGameTitleID+"\" is not a valid type"); alert.initOwner(main.primaryStage); alert.showAndWait(); }else{ Alert updateAlert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser updateAlert.setTitle("cemu_UI"); updateAlert.setHeaderText("update "+selectedGameTitle); updateAlert.setContentText("pleas select the update root directory"); updateAlert.initOwner(main.primaryStage); Optional result = updateAlert.showAndWait(); if (result.get() == ButtonType.OK){ DirectoryChooser directoryChooser = new DirectoryChooser(); File selectedDirecroty = directoryChooser.showDialog(main.primaryStage); updatePath = selectedDirecroty.getAbsolutePath(); String[] parts = titleID.split("-"); //split string into 2 parts at "-" File srcDir = new File(updatePath); File destDir = new File(cemuPath+"\\mlc01\\usr\\title\\"+parts[0]+"\\"+parts[1]); System.out.println(updatePath); System.out.println(destDir.toString()); if(destDir.exists() != true){ destDir.mkdir(); } try { System.out.println("copying files..."); playBtn.setText("updating..."); playBtn.setDisable(true); FileUtils.copyDirectory(srcDir, destDir); //TODO progress indicator playBtn.setText("play"); playBtn.setDisable(false); System.out.println("done!"); } catch (IOException e) { e.printStackTrace(); } } else { updatePath = null; } } } }); addDLC.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { String titleID = selectedGameTitleID; String dlcPath; System.out.println("add DLC: "+selectedGameTitleID); if(selectedGameTitleID == null){ System.out.println("trying to add a dlc to null! null is not valid!"); Alert alert = new Alert(AlertType.WARNING); alert.setTitle("add DLC"); alert.setHeaderText("cemu_UI"); alert.setContentText("please select a game, \""+selectedGameTitleID+"\" is not a valid type"); alert.initOwner(main.primaryStage); alert.showAndWait(); }else{ Alert updateAlert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser updateAlert.setTitle("cemu_UI"); updateAlert.setHeaderText("add a DLC to "+selectedGameTitle); updateAlert.setContentText("pleas select the DLC root directory"); updateAlert.initOwner(main.primaryStage); Optional result = updateAlert.showAndWait(); if (result.get() == ButtonType.OK){ DirectoryChooser directoryChooser = new DirectoryChooser(); File selectedDirecroty = directoryChooser.showDialog(main.primaryStage); dlcPath = selectedDirecroty.getAbsolutePath(); String[] parts = titleID.split("-"); //split string into 2 parts at "-" File srcDir = new File(dlcPath); File destDir = new File(cemuPath+"\\mlc01\\usr\\title\\"+parts[0]+"\\"+parts[1]+"\\aoc"); System.out.println(dlcPath); System.out.println(destDir.toString()); if(destDir.exists() != true){ destDir.mkdir(); } try { System.out.println("copying files..."); playBtn.setText("copying files..."); playBtn.setDisable(true); FileUtils.copyDirectory(srcDir, destDir); //TODO progress indicator playBtn.setText("play"); playBtn.setDisable(false); System.out.println("done!"); } catch (IOException e) { e.printStackTrace(); } } else { dlcPath = null; } } } }); gamesAnchorPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { @Override public void handle(MouseEvent event) { if (playTrue) { playBtnSlideOut(); } } }); topHBox.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { @Override public void handle(MouseEvent event) { if (playTrue) { playBtnSlideOut(); } } }); //Change-listener for TreeTable courseTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldVal, Object newVal){ selected = courseTreeTable.getSelectionModel().getSelectedIndex(); //get selected item //FIXME if a item is selected and you change the sorting,you can't select a new 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 { // System.out.println("http://smmdb.ddns.net/courseimg/" + id + "_full.jpg?v=3"); URL url = new URL("http://smmdb.ddns.net/courseimg/" + id + "_full.jpg?v=3"); Image image = new Image(url.toURI().toString()); smmdbImageView.setImage(image); } catch (MalformedURLException | URISyntaxException e) { e.printStackTrace(); smmdbImageView.setImage(close_black); } addCourseDescription(courses.get(i)); } } } }); helpLabel.setOnMouseClicked(new EventHandler() { @Override public void handle(MouseEvent mouseEvent) { if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){ System.out.println("I'll help you"); try { Desktop.getDesktop().browse(new URI("https://github.com/Seil0/cemu_UI/issues/3")); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } } } }); LOGGER.info("initializing Actions done!"); // System.out.println("initializing Actions done!"); } @FXML void detailsSlideoutBtnAction(ActionEvent event){ playBtnSlideOut(); } @FXML void aboutBtnAction(){ JFXDialogLayout content= new JFXDialogLayout(); content.setHeading(new Text("cemu_UI")); content.setBody(new Text("cemu_UI by @Seil0 \nVersion: "+version+" ("+buildNumber+") \""+versionName+"\" \nThis Application is made with free Software\nwww.kellerkinder.xyz")); content.setPrefSize(350, 170); StackPane stackPane = new StackPane(); stackPane.autosize(); JFXDialog dialog =new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true); JFXButton button=new JFXButton("Okay"); button.setOnAction(new EventHandler(){ @Override public void handle(ActionEvent event){ dialog.close(); } }); button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); button.setPrefHeight(32); button.setStyle(dialogBtnStyle); content.setActions(button); main.pane.getChildren().add(stackPane); AnchorPane.setTopAnchor(stackPane, (main.pane.getHeight()-content.getPrefHeight())/2); AnchorPane.setLeftAnchor(stackPane, (main.pane.getWidth()-content.getPrefWidth())/2); dialog.show(); } @FXML void settingsBtnAction(ActionEvent event) { if (smmdbTrue) { smmdbAnchorPane.setVisible(false); smmdbTrue = false; } if (settingsTrue) { settingsAnchorPane.setVisible(false); settingsTrue = false; saveSettings(); } else { settingsAnchorPane.setVisible(true); settingsTrue = true; } } @FXML void reloadRomsBtnAction() throws IOException{ reloadRomsBtn.setText("reloading..."); dbController.loadRomDirectory(getRomPath()); //TODO own thread Runtime.getRuntime().exec("java -jar cemu_UI.jar"); //start again (preventing Bugs) System.exit(0); //finishes itself } @FXML void smmdbBtnAction() { //show smmdbAnchorPane if (smmdbTrue) { smmdbAnchorPane.setVisible(false); smmdbTrue = false; } else { smmdbAnchorPane.setVisible(true); smmdbTrue = true; //start query courses.removeAll(courses); courses.addAll(smmdbApiQuery.startQuery()); //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()); root.getChildren().add(new TreeItem(helpCourse)); //add data to root-node } } } @FXML void playBtnAction(ActionEvent event) throws InterruptedException, IOException{ dbController.setLastPlayed(selectedGameTitleID); playGame = new playGame(this,dbController); playGame.start(); } @FXML void timePlayedBtnAction(ActionEvent event){ } @FXML void lastTimePlayedBtnAction(ActionEvent event){ } @FXML void cemuTFBtnAction(ActionEvent event) { File cemuDirectory = directoryChooser.showDialog(main.primaryStage); if(cemuDirectory == null){ System.out.println("No Directory selected"); }else{ setCemuPath(cemuDirectory.getAbsolutePath()); saveSettings(); cemuTextField.setText(getCemuPath()); try { Runtime.getRuntime().exec("java -jar cemu_UI.jar"); //start again System.exit(0); //finishes itself } catch (IOException e) { System.out.println("es ist ein Fehler aufgetreten"); e.printStackTrace(); } } } @FXML void romTFBtnAction(ActionEvent event) { File romDirectory = directoryChooser.showDialog(main.primaryStage); if(romDirectory == null){ System.out.println("No Directory selected"); }else{ setRomPath(romDirectory.getAbsolutePath()); saveSettings(); cemuTextField.setText(getCemuPath()); try { Runtime.getRuntime().exec("java -jar cemu_UI.jar"); //start again System.exit(0); //finishes itself } catch (IOException e) { System.out.println("es ist ein Fehler aufgetreten"); e.printStackTrace(); } } } @FXML void smmdbDownloadBtnAction(ActionEvent event){ String downloadUrl = "http://smmdb.ddns.net/api/downloadcourse?id=" + id + "&type=zip"; String downloadFileURL = getCemuPath() + "/" + id + ".zip"; //getCemuPath() + "/" + smmID + "/" + id + ".rar" String outputFile = getCemuPath() + "/"; try { 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(); System.out.println("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()) { 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(); } } try { ZipFile zipFile = new ZipFile(source); zipFile.extractAll(destination); //rename zipfile File course = new File(destination + "/course000"); course.renameTo( new File(destination + "/" + courseName)); System.out.println("Added new course: " + courseName + ", full path is: " + destination + "/" + courseName); } catch (ZipException e) { e.printStackTrace(); System.err.println("an error occurred during unziping the file!"); } downloadFile.delete(); } catch (IOException e) { System.err.println("something went wrong during downloading the course"); e.printStackTrace(); } } @FXML void cemuTextFieldAction(ActionEvent event){ setCemuPath(cemuTextField.getText()); saveSettings(); } @FXML void romTextFieldAction(ActionEvent event){ setRomPath(romTextField.getText()); saveSettings(); } @FXML void fullscreenToggleBtnAction(ActionEvent event){ if(fullscreen){ fullscreen = false; }else{ fullscreen = true; } saveSettings(); } @FXML void cloudSyncToggleBtnAction(ActionEvent event){ if(cloudSync) { cloudSync = false; } else { JFXDialogLayout content= new JFXDialogLayout(); content.setHeading(new Text("activate cloud savegame sync (beta)")); content.setBody(new Text("You just activate the cloud savegame sync function of cemu_UI, \nwhich is currently in beta. Are you sure you want to do this?")); StackPane stackPane = new StackPane(); stackPane.autosize(); JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true); JFXButton okayBtn = new JFXButton("Okay"); okayBtn.setOnAction(new EventHandler(){ @Override public void handle(ActionEvent event){ cloudSync = true; //TODO rework for other cloud services cloudService = "GoogleDrive"; main.cloudController.initializeConnection(getCloudService(), getCemuPath()); main.cloudController.sync(getCloudService(), getCemuPath()); saveSettings(); dialog.close(); } }); JFXButton cancelBtn = new JFXButton("Cancel"); cancelBtn.setOnAction(new EventHandler(){ @Override public void handle(ActionEvent event){ cloudSyncToggleBtn.setSelected(false); dialog.close(); } }); Label placeholder = new Label(); placeholder.setPrefSize(15, 10); okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); okayBtn.setPrefHeight(32); cancelBtn.setPrefHeight(32); okayBtn.setStyle(dialogBtnStyle); cancelBtn.setStyle(dialogBtnStyle); content.setActions(cancelBtn, placeholder, okayBtn); content.setPrefSize(419, 140); main.pane.getChildren().add(stackPane); AnchorPane.setTopAnchor(stackPane, (main.pane.getHeight()-content.getPrefHeight())/2); AnchorPane.setLeftAnchor(stackPane, (main.pane.getWidth()-content.getPrefWidth())/2); dialog.show(); } } @FXML void colorPickerAction(ActionEvent event){ editColor(colorPicker.getValue().toString()); applyColor(); } @FXML void addBtnAction(ActionEvent event){ boolean exit = false; String romPath = null; String coverPath = null; String coverName = null; String title = null; String titleID = null; File pictureCache; TextInputDialog titleDialog = new TextInputDialog(); titleDialog.setTitle("cemu_UI"); titleDialog.setHeaderText("add new Game"); titleDialog.setContentText("Please enter the name of the game you want to add:"); titleDialog.initOwner(main.primaryStage); Optional titleResult = titleDialog.showAndWait(); if (titleResult.isPresent()){ title = titleResult.get(); }else{ exit = true; } if(exit == false){ TextInputDialog titleIDDialog = new TextInputDialog(); titleIDDialog.setTitle("cemu_UI"); titleIDDialog.setHeaderText("add new Game"); titleIDDialog.setContentText("Please enter the title-ID (12345678-12345678) \nof the game you want to add:"); titleIDDialog.initOwner(main.primaryStage); Optional titleIDResult = titleIDDialog.showAndWait(); if (titleIDResult.isPresent()){ titleID = titleIDResult.get(); }else{ exit = true; } } if(exit == false){ Alert romAlert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser romAlert.setTitle("cemu_UI"); romAlert.setHeaderText("add new Game"); romAlert.setContentText("Please select the .rpx file from the game you want to add."); romAlert.initOwner(main.primaryStage); Optional result = romAlert.showAndWait(); if (result.get() == ButtonType.OK){ FileChooser directoryChooser = new FileChooser(); File selectedDirectory = directoryChooser.showOpenDialog(main.primaryStage); romPath = selectedDirectory.getAbsolutePath(); } else { exit = true; } } if(exit == false){ Alert coverAlert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser coverAlert.setTitle("cemu_UI"); coverAlert.setHeaderText("add new Game"); coverAlert.setContentText("Please select the cover for the game you want to add."); coverAlert.initOwner(main.primaryStage); Optional coverResult = coverAlert.showAndWait(); if (coverResult.get() == ButtonType.OK){ FileChooser directoryChooser = new FileChooser(); File selectedDirectory = directoryChooser.showOpenDialog(main.primaryStage); coverPath = selectedDirectory.getAbsolutePath(); } else { exit = true; } } /** * if exit == true then don't add a rom * else convert the cover to .png add copy it into the picture cache * then add the rom to the local_roms database */ if(exit){ System.out.println("No parameter set!"); }else{ coverName = new File(coverPath).getName(); try { if(System.getProperty("os.name").equals("Linux")){ pictureCache = pictureCacheLinux; }else{ pictureCache = pictureCacheWin; } 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); ImageIO.write(resizeImagePNG, "png", new File(pictureCache+"\\"+coverName)); //save image to pictureCache coverPath = pictureCache+"\\"+coverName; } catch (IOException e) { System.out.println("Ops something went wrong!"); } try { dbController.addRom(title, coverPath, romPath, titleID, "", "", "", "0"); dbController.loadSingleRom(titleID); } catch (SQLException e) { // Auto-generated catch block System.out.println("Oops, something went wrong! Error during adding a game."); e.printStackTrace(); } } } /** * add game to the program and initialize all needed actions (start, time stamps, titleID) * @param title : game title * @param coverPath : path to cover (cache) * @param romPath : path to rom file (.rpx) * @param titleID : rom ID */ void addGame(String title, String coverPath, String romPath, String titleID){ ImageView imageView = new ImageView(); Label gameTitleLabel = new Label(title); File coverFile = new File(coverPath); VBox VBox = new VBox(); JFXButton gameBtn = new JFXButton(); Image coverImage = new Image(coverFile.toURI().toString()); generatePosition(); System.out.println("add " + getxPos()); //TODO debug VBox.setLayoutX(getxPos()); VBox.setLayoutY(getyPos()); VBox.getChildren().addAll(gameTitleLabel,gameBtn); gameTitleLabel.setMaxWidth(200); gameTitleLabel.setPadding(new Insets(0,0,0,8)); gameTitleLabel.setFont(Font.font("System", FontWeight.BOLD, 14)); imageView.setImage(coverImage); imageView.setFitHeight(300); imageView.setFitWidth(200); gameBtn.setGraphic(imageView); gameBtn.setContextMenu(gameContextMenu); gameBtn.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 3); "); gameBtn.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { @Override public void handle(MouseEvent event) { System.out.println("selected: "+title+"; ID: "+titleID); //getting the selected game index by comparing event.getSource() with games.get(i).getButton() for(int i=0; i 60){ int hoursPlayed = (int) Math.floor(Integer.parseInt(dbController.getTimePlayed(titleID))/60); int minutesPlayed = Integer.parseInt(dbController.getTimePlayed(titleID))-60*hoursPlayed; timePlayedBtn.setText(hoursPlayed+"h "+minutesPlayed+"min"); }else{ timePlayedBtn.setText(dbController.getTimePlayed(titleID)+ " min"); } } if (!playTrue) { playBtnSlideIn(); } if (menuTrue) { sideMenuSlideOut(); } } }); games.add(new UIROMDataType(VBox, gameTitleLabel, gameBtn, titleID, romPath)); } //add all games to the UI (only called on startup) void addUIData(){ for(int i=0; i> 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 String getCemuPath() { return cemuPath; } public void setCemuPath(String cemuPath) { this.cemuPath = cemuPath; } public String getRomPath() { return romPath; } public void setRomPath(String romPath) { this.romPath = romPath; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getxPos() { return xPos; } public void setxPos(int xPos) { this.xPos = xPos; } public int getyPos() { return yPos; } public void setyPos(int yPos) { this.yPos = yPos; } public int getxPosHelper() { return xPosHelper; } public void setxPosHelper(int xPosHelper) { this.xPosHelper = xPosHelper; } public boolean isFullscreen() { return fullscreen; } public void setFullscreen(boolean fullscreen) { this.fullscreen = fullscreen; } public boolean isCloudSync() { return cloudSync; } public void setCloudSync(boolean cloudSync) { this.cloudSync = cloudSync; } 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 String getCloudService() { return cloudService; } public void setCloudService(String cloudService) { this.cloudService = cloudService; } public JFXButton getPlayBtn() { return playBtn; } public void setPlayBtn(JFXButton playBtn) { this.playBtn = playBtn; } }