2019-02-18 03:06:49 +03:00
|
|
|
package nsusbloader.Controllers;
|
2019-02-10 04:59:54 +03:00
|
|
|
|
2019-02-15 05:44:39 +03:00
|
|
|
import javafx.collections.FXCollections;
|
|
|
|
import javafx.collections.ObservableList;
|
2019-02-10 04:59:54 +03:00
|
|
|
import javafx.fxml.FXML;
|
|
|
|
import javafx.fxml.Initializable;
|
2019-02-16 04:34:30 +03:00
|
|
|
import javafx.scene.control.*;
|
2019-03-14 23:41:17 +03:00
|
|
|
import javafx.scene.input.DragEvent;
|
|
|
|
import javafx.scene.input.TransferMode;
|
2019-02-15 05:44:39 +03:00
|
|
|
import javafx.scene.layout.Pane;
|
2019-02-10 04:59:54 +03:00
|
|
|
import javafx.scene.layout.Region;
|
|
|
|
import javafx.stage.FileChooser;
|
2019-02-18 03:06:49 +03:00
|
|
|
import nsusbloader.AppPreferences;
|
|
|
|
import nsusbloader.MediatorControl;
|
2019-03-17 19:45:51 +03:00
|
|
|
import nsusbloader.NET.NETCommunications;
|
2019-02-18 03:06:49 +03:00
|
|
|
import nsusbloader.NSLMain;
|
2019-03-17 19:45:51 +03:00
|
|
|
import nsusbloader.ServiceWindow;
|
2019-03-14 21:28:20 +03:00
|
|
|
import nsusbloader.USB.UsbCommunications;
|
2019-02-10 04:59:54 +03:00
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.net.URL;
|
2019-03-14 23:41:17 +03:00
|
|
|
import java.util.ArrayList;
|
2019-02-10 04:59:54 +03:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.ResourceBundle;
|
2019-03-19 05:06:18 +03:00
|
|
|
import java.util.function.UnaryOperator;
|
2019-02-10 04:59:54 +03:00
|
|
|
|
|
|
|
public class NSLMainController implements Initializable {
|
|
|
|
|
|
|
|
private ResourceBundle resourceBundle;
|
|
|
|
|
|
|
|
@FXML
|
2019-02-17 18:38:07 +03:00
|
|
|
public TextArea logArea; // Accessible from Mediator
|
2019-02-10 04:59:54 +03:00
|
|
|
@FXML
|
|
|
|
private Button selectNspBtn;
|
|
|
|
@FXML
|
|
|
|
private Button uploadStopBtn;
|
|
|
|
private Region btnUpStopImage;
|
|
|
|
@FXML
|
2019-02-17 18:38:07 +03:00
|
|
|
public ProgressBar progressBar; // Accessible from Mediator
|
2019-02-15 05:44:39 +03:00
|
|
|
@FXML
|
2019-03-17 19:45:51 +03:00
|
|
|
private ChoiceBox<String> choiceProtocol, choiceNetUsb;
|
2019-02-15 05:44:39 +03:00
|
|
|
@FXML
|
|
|
|
private Button switchThemeBtn;
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
private Pane specialPane;
|
2019-02-10 04:59:54 +03:00
|
|
|
|
2019-02-16 04:34:30 +03:00
|
|
|
@FXML
|
2019-02-17 18:38:07 +03:00
|
|
|
public NSTableViewController tableFilesListController; // Accessible from Mediator
|
2019-03-17 19:45:51 +03:00
|
|
|
@FXML
|
2019-03-18 19:12:11 +03:00
|
|
|
private SettingsController SettingsTabController;
|
2019-03-17 19:45:51 +03:00
|
|
|
@FXML
|
|
|
|
private TextField nsIpTextField;
|
|
|
|
@FXML
|
|
|
|
private Label nsIpLbl;
|
2019-02-16 04:34:30 +03:00
|
|
|
|
2019-02-18 05:40:19 +03:00
|
|
|
private UsbCommunications usbCommunications;
|
2019-03-18 19:12:11 +03:00
|
|
|
private Thread workThread;
|
2019-02-10 04:59:54 +03:00
|
|
|
|
2019-02-15 05:44:39 +03:00
|
|
|
private String previouslyOpenedPath;
|
|
|
|
|
2019-02-10 04:59:54 +03:00
|
|
|
@Override
|
|
|
|
public void initialize(URL url, ResourceBundle rb) {
|
|
|
|
this.resourceBundle = rb;
|
2019-02-18 03:06:49 +03:00
|
|
|
logArea.setText(rb.getString("logsGreetingsMessage")+" "+ NSLMain.appVersion+"!\n");
|
2019-02-10 04:59:54 +03:00
|
|
|
if (System.getProperty("os.name").toLowerCase().startsWith("lin"))
|
|
|
|
if (!System.getProperty("user.name").equals("root"))
|
|
|
|
logArea.appendText(rb.getString("logsEnteredAsMsg1")+System.getProperty("user.name")+"\n"+rb.getString("logsEnteredAsMsg2") + "\n");
|
|
|
|
|
|
|
|
logArea.appendText(rb.getString("logsGreetingsMessage2")+"\n");
|
|
|
|
|
2019-02-17 18:38:07 +03:00
|
|
|
MediatorControl.getInstance().setController(this);
|
2019-02-10 04:59:54 +03:00
|
|
|
|
2019-02-15 05:44:39 +03:00
|
|
|
specialPane.getStyleClass().add("special-pane-as-border"); // UI hacks
|
|
|
|
|
2019-02-10 04:59:54 +03:00
|
|
|
uploadStopBtn.setDisable(true);
|
|
|
|
selectNspBtn.setOnAction(e->{ selectFilesBtnAction(); });
|
2019-02-11 17:33:53 +03:00
|
|
|
uploadStopBtn.setOnAction(e->{ uploadBtnAction(); });
|
2019-02-10 04:59:54 +03:00
|
|
|
|
2019-02-17 18:38:07 +03:00
|
|
|
selectNspBtn.getStyleClass().add("buttonSelect");
|
|
|
|
|
2019-02-10 04:59:54 +03:00
|
|
|
this.btnUpStopImage = new Region();
|
|
|
|
btnUpStopImage.getStyleClass().add("regionUpload");
|
|
|
|
//uploadStopBtn.getStyleClass().remove("button");
|
|
|
|
uploadStopBtn.getStyleClass().add("buttonUp");
|
|
|
|
uploadStopBtn.setGraphic(btnUpStopImage);
|
2019-02-15 05:44:39 +03:00
|
|
|
|
2019-02-16 04:34:30 +03:00
|
|
|
ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
|
2019-02-15 05:44:39 +03:00
|
|
|
choiceProtocol.setItems(choiceProtocolList);
|
2019-03-17 19:45:51 +03:00
|
|
|
choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol());
|
|
|
|
choiceProtocol.setOnAction(e-> {
|
|
|
|
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem());
|
|
|
|
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) {
|
|
|
|
choiceNetUsb.setDisable(true);
|
|
|
|
nsIpLbl.setVisible(false);
|
|
|
|
nsIpTextField.setVisible(false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
choiceNetUsb.setDisable(false);
|
|
|
|
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")) {
|
|
|
|
nsIpLbl.setVisible(true);
|
|
|
|
nsIpTextField.setVisible(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}); // Add listener to notify tableView controller
|
2019-02-16 17:58:26 +03:00
|
|
|
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller
|
2019-02-15 05:44:39 +03:00
|
|
|
|
2019-03-17 19:45:51 +03:00
|
|
|
ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET");
|
|
|
|
choiceNetUsb.setItems(choiceNetUsbList);
|
|
|
|
choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb());
|
|
|
|
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) {
|
|
|
|
choiceNetUsb.setDisable(true);
|
|
|
|
}
|
|
|
|
choiceNetUsb.setOnAction(e->{
|
|
|
|
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){
|
|
|
|
nsIpLbl.setVisible(true);
|
|
|
|
nsIpTextField.setVisible(true);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
nsIpLbl.setVisible(false);
|
|
|
|
nsIpTextField.setVisible(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
nsIpTextField.setText(AppPreferences.getInstance().getNsIp());
|
|
|
|
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil") && choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){
|
|
|
|
nsIpLbl.setVisible(true);
|
|
|
|
nsIpTextField.setVisible(true);
|
|
|
|
}
|
2019-03-19 05:06:18 +03:00
|
|
|
nsIpTextField.setTextFormatter(new TextFormatter<>(change -> {
|
|
|
|
if (change.getControlNewText().contains(" ") | change.getControlNewText().contains("\t"))
|
|
|
|
return null;
|
|
|
|
else
|
|
|
|
return change;
|
|
|
|
}));
|
2019-02-15 05:44:39 +03:00
|
|
|
this.previouslyOpenedPath = null;
|
|
|
|
|
2019-02-16 04:34:30 +03:00
|
|
|
Region btnSwitchImage = new Region();
|
2019-02-15 05:44:39 +03:00
|
|
|
btnSwitchImage.getStyleClass().add("regionLamp");
|
|
|
|
switchThemeBtn.setGraphic(btnSwitchImage);
|
|
|
|
this.switchThemeBtn.setOnAction(e->switchTheme());
|
2019-02-18 03:06:49 +03:00
|
|
|
|
|
|
|
previouslyOpenedPath = AppPreferences.getInstance().getRecent();
|
2019-02-16 04:34:30 +03:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Changes UI theme on the go
|
|
|
|
* */
|
2019-02-15 05:44:39 +03:00
|
|
|
private void switchTheme(){
|
2019-02-18 03:06:49 +03:00
|
|
|
if (switchThemeBtn.getScene().getStylesheets().get(0).equals("/res/app_dark.css")) {
|
|
|
|
switchThemeBtn.getScene().getStylesheets().remove("/res/app_dark.css");
|
2019-02-15 05:44:39 +03:00
|
|
|
switchThemeBtn.getScene().getStylesheets().add("/res/app_light.css");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switchThemeBtn.getScene().getStylesheets().remove("/res/app_light.css");
|
2019-02-18 03:06:49 +03:00
|
|
|
switchThemeBtn.getScene().getStylesheets().add("/res/app_dark.css");
|
2019-02-15 05:44:39 +03:00
|
|
|
}
|
2019-02-18 05:40:19 +03:00
|
|
|
AppPreferences.getInstance().setTheme(switchThemeBtn.getScene().getStylesheets().get(0));
|
2019-02-10 04:59:54 +03:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Functionality for selecting NSP button.
|
|
|
|
* Uses setReady and setNotReady to simplify code readability.
|
|
|
|
* */
|
|
|
|
private void selectFilesBtnAction(){
|
|
|
|
List<File> filesList;
|
|
|
|
FileChooser fileChooser = new FileChooser();
|
2019-02-11 15:09:23 +03:00
|
|
|
fileChooser.setTitle(resourceBundle.getString("btnFileOpen"));
|
2019-02-18 03:06:49 +03:00
|
|
|
|
|
|
|
File validator = new File(previouslyOpenedPath);
|
|
|
|
if (validator.exists())
|
|
|
|
fileChooser.setInitialDirectory(validator); // TODO: read from prefs
|
|
|
|
else
|
2019-02-15 05:44:39 +03:00
|
|
|
fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: read from prefs
|
2019-02-18 03:06:49 +03:00
|
|
|
|
|
|
|
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
|
2019-02-10 04:59:54 +03:00
|
|
|
|
|
|
|
filesList = fileChooser.showOpenMultipleDialog(logArea.getScene().getWindow());
|
2019-02-15 05:44:39 +03:00
|
|
|
if (filesList != null && !filesList.isEmpty()) {
|
2019-02-16 17:58:26 +03:00
|
|
|
tableFilesListController.setFiles(filesList);
|
|
|
|
uploadStopBtn.setDisable(false);
|
2019-02-15 05:44:39 +03:00
|
|
|
previouslyOpenedPath = filesList.get(0).getParent();
|
|
|
|
}
|
2019-02-10 04:59:54 +03:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* It's button listener when no transmission executes
|
|
|
|
* */
|
2019-02-11 17:33:53 +03:00
|
|
|
private void uploadBtnAction(){
|
2019-03-18 19:12:11 +03:00
|
|
|
if ((workThread == null || !workThread.isAlive())){
|
2019-03-17 19:45:51 +03:00
|
|
|
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf") ||
|
|
|
|
(
|
|
|
|
choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil")
|
|
|
|
&& choiceNetUsb.getSelectionModel().getSelectedItem().equals("USB")
|
|
|
|
)
|
|
|
|
){
|
|
|
|
List<File> nspToUpload;
|
|
|
|
if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) {
|
|
|
|
logArea.setText(resourceBundle.getString("logsNoFolderFileSelected"));
|
|
|
|
return;
|
2019-03-18 19:12:11 +03:00
|
|
|
}
|
|
|
|
else {
|
2019-03-17 19:45:51 +03:00
|
|
|
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n");
|
|
|
|
for (File item: nspToUpload)
|
|
|
|
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
|
|
|
}
|
|
|
|
usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem());
|
2019-03-18 19:12:11 +03:00
|
|
|
workThread = new Thread(usbCommunications);
|
|
|
|
workThread.setDaemon(true);
|
|
|
|
workThread.start();
|
2019-03-17 19:45:51 +03:00
|
|
|
}
|
|
|
|
else { // NET INSTALL OVER TINFOIL
|
2019-03-18 19:12:11 +03:00
|
|
|
if (SettingsTabController.isNsIpValidate() && !nsIpTextField.getText().trim().matches("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"))
|
2019-03-17 19:45:51 +03:00
|
|
|
if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"),resourceBundle.getString("windowBodyBadIp")))
|
|
|
|
return;
|
|
|
|
String nsIP = nsIpTextField.getText().trim();
|
2019-03-18 19:12:11 +03:00
|
|
|
|
|
|
|
List<File> nspToUpload;
|
|
|
|
if (!SettingsTabController.getExpertModeSelected()) {
|
|
|
|
if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) {
|
|
|
|
logArea.setText(resourceBundle.getString("logsNoFolderFileSelected"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n");
|
|
|
|
for (File item: nspToUpload)
|
|
|
|
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
|
|
|
}
|
|
|
|
NETCommunications netCommunications = new NETCommunications(nspToUpload, nsIP); // TODO: move somewhere
|
|
|
|
workThread = new Thread(netCommunications);
|
|
|
|
workThread.setDaemon(true);
|
|
|
|
workThread.start();
|
2019-03-17 19:45:51 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// TODO; pass to another constructor
|
|
|
|
}
|
2019-02-16 17:58:26 +03:00
|
|
|
}
|
2019-02-10 04:59:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* It's button listener when transmission in progress
|
|
|
|
* */
|
|
|
|
private void stopBtnAction(){
|
2019-03-18 19:12:11 +03:00
|
|
|
if (workThread != null && workThread.isAlive()){
|
|
|
|
usbCommunications.cancel(false); // TODO: add something abstract to use also for network
|
2019-02-10 04:59:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
|
|
|
|
* Called from mediator
|
|
|
|
* */
|
2019-02-18 03:06:49 +03:00
|
|
|
public void notifyTransmissionStarted(boolean isTransmissionStarted){
|
2019-02-10 04:59:54 +03:00
|
|
|
if (isTransmissionStarted) {
|
|
|
|
selectNspBtn.setDisable(true);
|
|
|
|
uploadStopBtn.setOnAction(e->{ stopBtnAction(); });
|
|
|
|
|
|
|
|
uploadStopBtn.setText(resourceBundle.getString("btnStop"));
|
|
|
|
|
|
|
|
btnUpStopImage.getStyleClass().remove("regionUpload");
|
|
|
|
btnUpStopImage.getStyleClass().add("regionStop");
|
|
|
|
|
|
|
|
uploadStopBtn.getStyleClass().remove("buttonUp");
|
|
|
|
uploadStopBtn.getStyleClass().add("buttonStop");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
selectNspBtn.setDisable(false);
|
2019-02-11 17:33:53 +03:00
|
|
|
uploadStopBtn.setOnAction(e->{ uploadBtnAction(); });
|
2019-02-10 04:59:54 +03:00
|
|
|
|
|
|
|
uploadStopBtn.setText(resourceBundle.getString("btnUpload"));
|
|
|
|
|
|
|
|
btnUpStopImage.getStyleClass().remove("regionStop");
|
|
|
|
btnUpStopImage.getStyleClass().add("regionUpload");
|
|
|
|
|
|
|
|
uploadStopBtn.getStyleClass().remove("buttonStop");
|
|
|
|
uploadStopBtn.getStyleClass().add("buttonUp");
|
|
|
|
}
|
|
|
|
}
|
2019-03-15 04:09:04 +03:00
|
|
|
/**
|
|
|
|
* Crunch. Now you see that I'm not a programmer.. This function called from NSTableViewController
|
|
|
|
* */
|
2019-03-16 02:43:14 +03:00
|
|
|
public void disableUploadStopBtn(boolean disable){
|
|
|
|
uploadStopBtn.setDisable(disable);
|
2019-03-15 04:09:04 +03:00
|
|
|
}
|
2019-03-14 23:41:17 +03:00
|
|
|
/**
|
|
|
|
* Drag-n-drop support (dragOver consumer)
|
|
|
|
* */
|
|
|
|
@FXML
|
|
|
|
private void handleDragOver(DragEvent event){
|
|
|
|
if (event.getDragboard().hasFiles())
|
|
|
|
event.acceptTransferModes(TransferMode.ANY);
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Drag-n-drop support (drop consumer)
|
|
|
|
* */
|
|
|
|
@FXML
|
|
|
|
private void handleDrop(DragEvent event){
|
2019-03-16 02:43:14 +03:00
|
|
|
if (MediatorControl.getInstance().getTransferActive()) {
|
|
|
|
event.setDropCompleted(true);
|
|
|
|
return;
|
|
|
|
}
|
2019-03-14 23:41:17 +03:00
|
|
|
List<File> filesDropped = new ArrayList<>();
|
|
|
|
try {
|
|
|
|
for (File fileOrDir : event.getDragboard().getFiles()) {
|
|
|
|
if (fileOrDir.getName().toLowerCase().endsWith(".nsp"))
|
|
|
|
filesDropped.add(fileOrDir);
|
|
|
|
else if (fileOrDir.isDirectory())
|
|
|
|
for (File file : fileOrDir.listFiles())
|
|
|
|
if (file.getName().toLowerCase().endsWith(".nsp"))
|
|
|
|
filesDropped.add(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (SecurityException se){
|
|
|
|
se.printStackTrace();
|
|
|
|
}
|
2019-03-16 02:43:14 +03:00
|
|
|
if (!filesDropped.isEmpty())
|
|
|
|
tableFilesListController.setFiles(filesDropped);
|
2019-03-14 23:41:17 +03:00
|
|
|
|
|
|
|
event.setDropCompleted(true);
|
|
|
|
}
|
2019-02-18 03:06:49 +03:00
|
|
|
/**
|
|
|
|
* Save preferences before exit
|
|
|
|
* */
|
2019-03-19 05:06:18 +03:00
|
|
|
public void exit(){ // TODO: add method to set all in AppPreferences
|
|
|
|
AppPreferences.getInstance().setAll(
|
|
|
|
choiceProtocol.getSelectionModel().getSelectedItem(),
|
|
|
|
previouslyOpenedPath,
|
|
|
|
choiceNetUsb.getSelectionModel().getSelectedItem(),
|
|
|
|
nsIpTextField.getText().trim(),
|
|
|
|
SettingsTabController.isNsIpValidate(),
|
|
|
|
SettingsTabController.getExpertModeSelected(),
|
|
|
|
SettingsTabController.getAutoIpSelected(),
|
|
|
|
SettingsTabController.getRandPortSelected(),
|
|
|
|
SettingsTabController.getNotServeSelected(),
|
|
|
|
SettingsTabController.getHostIp(),
|
|
|
|
SettingsTabController.getHostPort(),
|
|
|
|
SettingsTabController.getHostExtra()
|
|
|
|
);
|
2019-02-18 03:06:49 +03:00
|
|
|
}
|
2019-02-10 04:59:54 +03:00
|
|
|
}
|