From ad23eb0c820bb0a877cd0ab81d4b5c772556e745 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Sat, 16 Feb 2019 17:58:26 +0300 Subject: [PATCH] v0.2-development intermediate results of UI updates --- .../nsusbloader/Controllers/NSLRowModel.java | 3 + .../Controllers/NSTableViewController.java | 53 ++++++++---- .../java/nsusbloader/NSLMainController.java | 37 ++++---- src/main/resources/NSLMain.fxml | 2 +- src/main/resources/locale_en.properties | 4 + src/main/resources/locale_ru.properties | 4 + src/main/resources/res/app.css | 75 ++++++++++++---- src/main/resources/res/app_light.css | 85 ++++++++++++++----- 8 files changed, 188 insertions(+), 75 deletions(-) diff --git a/src/main/java/nsusbloader/Controllers/NSLRowModel.java b/src/main/java/nsusbloader/Controllers/NSLRowModel.java index 098ad70..7b8ba7a 100644 --- a/src/main/java/nsusbloader/Controllers/NSLRowModel.java +++ b/src/main/java/nsusbloader/Controllers/NSLRowModel.java @@ -9,12 +9,14 @@ public class NSLRowModel { private String status; // 0 = unknown, 1 = uploaded, 2 = bad file private File nspFile; private String nspFileName; + private String nspFileSize; private boolean markForUpload; NSLRowModel(File nspFile, boolean checkBoxValue){ this.nspFile = nspFile; this.markForUpload = checkBoxValue; this.nspFileName = nspFile.getName(); + this.nspFileSize = String.format("%.2f", nspFile.length()/1024.0/1024.0); this.status = ""; } // Model methods start @@ -24,6 +26,7 @@ public class NSLRowModel { public String getNspFileName(){ return nspFileName; } + public String getNspFileSize() { return nspFileSize; } public boolean isMarkForUpload() { return markForUpload; } diff --git a/src/main/java/nsusbloader/Controllers/NSTableViewController.java b/src/main/java/nsusbloader/Controllers/NSTableViewController.java index 1d89839..0ce6fa1 100644 --- a/src/main/java/nsusbloader/Controllers/NSTableViewController.java +++ b/src/main/java/nsusbloader/Controllers/NSTableViewController.java @@ -27,20 +27,25 @@ public class NSTableViewController implements Initializable { private TableView table; private ObservableList rowsObsLst; + private String protocol; + @Override public void initialize(URL url, ResourceBundle resourceBundle) { rowsObsLst = FXCollections.observableArrayList(); table.setPlaceholder(new Label()); - TableColumn statusColumn = new TableColumn<>("Status"); // TODO: Localization - TableColumn fileNameColumn = new TableColumn<>("File Name"); // TODO: Localization - TableColumn uploadColumn = new TableColumn<>("Upload?"); // TODO: Localization + TableColumn statusColumn = new TableColumn<>(resourceBundle.getString("tableStatusLbl")); + TableColumn fileNameColumn = new TableColumn<>(resourceBundle.getString("tableFileNameLbl")); + TableColumn fileSizeColumn = new TableColumn<>(resourceBundle.getString("tableSizeLbl")); + TableColumn uploadColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl")); statusColumn.setMinWidth(70.0); - fileNameColumn.setMinWidth(270.0); + fileNameColumn.setMinWidth(250.0); + fileSizeColumn.setMinWidth(70.0); uploadColumn.setMinWidth(70.0); statusColumn.setCellValueFactory(new PropertyValueFactory<>("status")); fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("nspFileName")); + fileSizeColumn.setCellValueFactory(new PropertyValueFactory<>("nspFileSize")); // >< uploadColumn.setCellValueFactory(new Callback, ObservableValue>() { @Override @@ -53,7 +58,7 @@ public class NSTableViewController implements Initializable { @Override public void changed(ObservableValue observableValue, Boolean oldValue, Boolean newValue) { model.setMarkForUpload(newValue); - // TODO: add reference to this general class method which will validate protocol and restict selection + restrictSelection(model); } }); @@ -70,19 +75,33 @@ public class NSTableViewController implements Initializable { }); table.setItems(rowsObsLst); - table.getColumns().addAll(statusColumn, fileNameColumn, uploadColumn); - - rowsObsLst.add(new NSLRowModel(new File("/tmp/dump_file"), true)); - rowsObsLst.add(new NSLRowModel(new File("/home/loper/тяжелые будни.mp4"), false)); - rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи.txt"), false)); + table.getColumns().addAll(statusColumn, fileNameColumn, fileSizeColumn, uploadColumn); + /* debug content + rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_2"), true)); rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_2"), false)); - rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_1"), false)); + rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_2"), false)); + rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_2"), true)); + */ + } + /** + * See uploadColumn callback. In case of GoldLeaf we have to restrict selection + * */ + private void restrictSelection(NSLRowModel modelChecked){ + if (!protocol.equals("TinFoil") && rowsObsLst.size() > 1) { // Tinfoil doesn't need any restrictions. If only one file in list, also useless + for (NSLRowModel model: rowsObsLst){ + if (model != modelChecked) + model.setMarkForUpload(false); + }table.refresh(); + } } /** * Add files when user selected them * */ - public void addFiles(List files, String protocol){ - rowsObsLst.clear(); + public void setFiles(List files){ + rowsObsLst.clear(); // TODO: consider table refresh + if (files == null) { + return; + } if (protocol.equals("TinFoil")){ for (File nspFile: files){ rowsObsLst.add(new NSLRowModel(nspFile, true)); @@ -119,7 +138,7 @@ public class NSTableViewController implements Initializable { /** * Update files in case something is wrong. Requested from UsbCommunications _OR_ PFS * */ - public void reportFileStatus(String fileName, FileStatus status){ + public void setFileStatus(String fileName, FileStatus status){ for (NSLRowModel model: rowsObsLst){ if (model.getNspFileName().equals(fileName)){ model.setStatus(status); @@ -129,10 +148,11 @@ public class NSTableViewController implements Initializable { /** * Called if selected different USB protocol * */ - public void protocolChangeEvent(String protocol){ + public void setNewProtocol(String newProtocol){ + protocol = newProtocol; if (rowsObsLst.isEmpty()) return; - if (protocol.equals("TinFoil")){ + if (newProtocol.equals("TinFoil")){ for (NSLRowModel model: rowsObsLst) model.setMarkForUpload(true); } @@ -143,4 +163,5 @@ public class NSTableViewController implements Initializable { } table.refresh(); } + } diff --git a/src/main/java/nsusbloader/NSLMainController.java b/src/main/java/nsusbloader/NSLMainController.java index 8871879..5b42206 100644 --- a/src/main/java/nsusbloader/NSLMainController.java +++ b/src/main/java/nsusbloader/NSLMainController.java @@ -2,7 +2,6 @@ package nsusbloader; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; @@ -13,6 +12,7 @@ import nsusbloader.Controllers.NSTableViewController; import java.io.File; import java.net.URL; +import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle; @@ -20,8 +20,6 @@ public class NSLMainController implements Initializable { private ResourceBundle resourceBundle; - private List nspToUpload; - @FXML private TextArea logArea; @FXML @@ -73,7 +71,8 @@ public class NSLMainController implements Initializable { ObservableList choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf"); choiceProtocol.setItems(choiceProtocolList); choiceProtocol.getSelectionModel().select(0); // TODO: shared settings - choiceProtocol.setOnAction(e->tableFilesListController.protocolChangeEvent(choiceProtocol.getSelectionModel().getSelectedItem())); + choiceProtocol.setOnAction(e->tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem())); // Add listener to notify tableView controller + tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller this.previouslyOpenedPath = null; @@ -117,29 +116,29 @@ public class NSLMainController implements Initializable { filesList = fileChooser.showOpenMultipleDialog(logArea.getScene().getWindow()); if (filesList != null && !filesList.isEmpty()) { - setReady(filesList); + tableFilesListController.setFiles(filesList); + uploadStopBtn.setDisable(false); previouslyOpenedPath = filesList.get(0).getParent(); } - else - setNotReady(resourceBundle.getString("logsNoFolderFileSelected")); - } - private void setReady(List filesList){ - logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n"); - for (File item: filesList) - logArea.appendText(" "+item.getAbsolutePath()+"\n"); - nspToUpload = filesList; - uploadStopBtn.setDisable(false); - } - private void setNotReady(String whyNotReady){ - logArea.setText(whyNotReady); - nspToUpload = null; - uploadStopBtn.setDisable(true); + else{ + tableFilesListController.setFiles(null); + uploadStopBtn.setDisable(true); + } } /** * It's button listener when no transmission executes * */ private void uploadBtnAction(){ if (usbThread == null || !usbThread.isAlive()){ + List nspToUpload; + if ((nspToUpload = tableFilesListController.getFiles()) == null) { + resourceBundle.getString("logsNoFolderFileSelected"); + return; + }else { + logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n"); + for (File item: nspToUpload) + logArea.appendText(" "+item.getAbsolutePath()+"\n"); + } UsbCommunications usbCommunications = new UsbCommunications(logArea, progressBar, nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem()); usbThread = new Thread(usbCommunications); usbThread.start(); diff --git a/src/main/resources/NSLMain.fxml b/src/main/resources/NSLMain.fxml index 47f8d14..ac38942 100644 --- a/src/main/resources/NSLMain.fxml +++ b/src/main/resources/NSLMain.fxml @@ -21,7 +21,7 @@ - + diff --git a/src/main/resources/locale_en.properties b/src/main/resources/locale_en.properties index 43f844e..17ee4b2 100644 --- a/src/main/resources/locale_en.properties +++ b/src/main/resources/locale_en.properties @@ -15,3 +15,7 @@ Dmitry Isaenko [developer.su] windowTitleConfirmWrongPFS0=Incorrect file type windowBodyConfirmWrongPFS0=Selected NSP file has incrrect starting symbols. Most likely it's corrupted.\n\ It's better to interrupt proccess now. Continue process anyway? +tableStatusLbl=Status +tableFileNameLbl=File name +tableSizeLbl=Size (~Mb) +tableUploadLbl=Upload? diff --git a/src/main/resources/locale_ru.properties b/src/main/resources/locale_ru.properties index adf9bfa..1c4d268 100644 --- a/src/main/resources/locale_ru.properties +++ b/src/main/resources/locale_ru.properties @@ -16,4 +16,8 @@ windowTitleConfirmWrongPFS0=\u041D\u0435\u043F\u0440\u0438\u0430\u0432\u0438\u04 windowBodyConfirmWrongPFS0=\u0412\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0444\u0430\u0439\u043B NSP \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B. \u041E\u043D \u043D\u0430\u0432\u0435\u0440\u043D\u044F\u043A\u0430 \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0451\u043D.\n\ \u041B\u0443\u0447\u0448\u0435 \u043E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C\u0441\u044F \u043F\u0440\u044F\u043C\u043E \u0441\u0435\u0439\u0447\u0430\u0441. \u0425\u043E\u0447\u0435\u0448\u044C \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0442\u044C \u043D\u0438 \u0441\u043C\u043E\u0442\u0440\u044F \u043D\u0438 \u043D\u0430 \u0447\u0442\u043E?\ +tableUploadLbl=\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044C? +tableSizeLbl=\u0420\u0430\u0437\u043C\u0435\u0440 (~\u041C\u0431) +tableFileNameLbl=\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430 +tableStatusLbl=\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 diff --git a/src/main/resources/res/app.css b/src/main/resources/res/app.css index ceba882..4cff086 100644 --- a/src/main/resources/res/app.css +++ b/src/main/resources/res/app.css @@ -13,7 +13,7 @@ -fx-text-fill: #f7fafa; -fx-effect: none; } -.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover{ +.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .choice-box:focused:hover{ -fx-background-color: #4f4f4f; -fx-border-color: #a4ffff; -fx-border-radius: 3; @@ -22,23 +22,24 @@ } .button:focused, .buttonStop:focused, .buttonUp:focused, .choice-box:focused{ -fx-background-color: #6a6a6a; + -fx-border-color: #6a6a6a; } -.button:pressed{ +.button:pressed, .button:pressed:hover{ -fx-background-color: #4f4f4f; -fx-border-color: #289de8; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #f7fafa; } -.buttonUp:pressed{ +.buttonUp:pressed, .buttonUp:pressed:hover{ -fx-background-color: #4f4f4f; -fx-border-color: #a2e019; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #f7fafa; } -.buttonStop:pressed{ +.buttonStop:pressed, .buttonStop:pressed:hover{ -fx-background-color: #4f4f4f; -fx-border-color: #fb582c; -fx-border-radius: 3; @@ -103,7 +104,7 @@ -fx-text-fill: #f7fafa; } -.choice-box:pressed{ +.choice-box:pressed, .choice-box:pressed:hover{ -fx-background-color: #4f4f4f; -fx-border-color: #eea11e; -fx-border-radius: 3; @@ -120,19 +121,47 @@ // Text color of focused item in the list .choice-box .menu-item:focused > .label { -fx-text-fill: #2d2d2d; } +// -======================== TAB PANE =========================- .tab-pane .tab SVGPath{ - -fx-fill: #66d053; - + -fx-fill: #f7fafa; +} +.tab-pane .tab:selected SVGPath{ + -fx-fill: #08f3ff; } .tab-pane .tab{ - -fx-background-color: #4f4f4f; + -fx-background-color: #424242; + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; + -fx-border-radius: 0 0 0 0; + -fx-border-width: 3 0 0 0; + -fx-border-color: #424242; } .tab-pane .tab:selected{ -fx-background-color: #2d2d2d; + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; + -fx-border-radius: 0 0 0 0; + -fx-border-width: 3 0 0 0; + -fx-border-color: #08f3ff; } + +.tab-pane > .tab-header-area { + -fx-background-insets: 0.0; + -fx-padding: 5 5 5 5; +} + +.tab-pane > .tab-header-area > .tab-header-background +{ + -fx-background-color: #424242; + +} +.tab-pane > .tab-header-area > .headers-region > .tab { + -fx-padding: 10; +} +// -=========================== TABLE ======================- .table-view { - -fx-background-color: #2d2d2d; + -fx-background-color: #4f4f4f; -fx-background-image: url(app_logo.png); -fx-background-position: center; -fx-background-repeat: no-repeat; @@ -145,21 +174,33 @@ } .table-view .column-header-background .label{ -fx-background-color: transparent; - -fx-text-fill: white; + -fx-text-fill: #08f3ff; } .table-view .column-header-background, .table-view .filler{ -fx-background-color: #4f4f4f; } -.table-row-cell:filled:selected { - -fx-background: -fx-control-inner-background ; - -fx-background-color: -fx-table-cell-border-color, -fx-background ; - -fx-background-insets: 0, 0 0 1 0 ; - -fx-table-cell-border-color: derive(-fx-color, 5%); + +.table-view .table-cell{ + -fx-text-fill: #f7fafa; } -.table-row-cell:odd:filled:selected { - -fx-background: -fx-control-inner-background-alt ; +.table-row-cell, .table-row-cell:filled:selected, .table-row-cell:selected{ + -fx-background-color: -fx-table-cell-border-color, #424242; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0.0em; /* 0 */ + -fx-table-cell-border-color: #f7fafa; } +.table-row-cell:odd, .table-row-cell:odd:filled:selected, .table-row-cell:odd:selected{ + -fx-background-color: -fx-table-cell-border-color, #4f4f4f; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0.0em; /* 0 */ + -fx-table-cell-border-color: #f7fafa; +} + + + + + .regionUpload{ -fx-shape: "M8,21V19H16V21H8M8,17V15H16V17H8M8,13V11H16V13H8M19,9H5L12,2L19,9Z"; -fx-background-color: #a2e019; diff --git a/src/main/resources/res/app_light.css b/src/main/resources/res/app_light.css index 5cce88c..cb5e0b5 100644 --- a/src/main/resources/res/app_light.css +++ b/src/main/resources/res/app_light.css @@ -14,39 +14,40 @@ -fx-effect: dropshadow(three-pass-box, #b4b4b4, 2, 0, 0, 0); } -.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover{ +.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .choice-box:focused:hover{ -fx-background-color: #fefefe; - -fx-border-color: #a4ffff; + -fx-border-color: #00caca; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #2c2c2c; } .button:focused, .buttonStop:focused, .buttonUp:focused, .choice-box:focused{ -fx-background-color: #cccccc; + -fx-border-color: #cccccc; } -.button:pressed{ +.button:pressed, .button:pressed:hover{ -fx-background-color: #fefefe; -fx-border-color: #289de8; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #2c2c2c; } -.buttonUp:pressed{ +.buttonUp:pressed, .buttonUp:pressed:hover{ -fx-background-color: #fefefe; -fx-border-color: #a2e019; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #2c2c2c; } -.buttonStop:pressed{ +.buttonStop:pressed, .buttonStop:pressed:hover{ -fx-background-color: #fefefe; -fx-border-color: #fb582c; -fx-border-radius: 3; -fx-border-width: 2; -fx-text-fill: #2c2c2c; } - +// -========================+ TextArea =====================- .text-area{ -fx-background-color: transparent; -fx-control-inner-background: #fefefe; @@ -104,7 +105,7 @@ -fx-text-fill: #2c2c2c; } -.choice-box:pressed{ +.choice-box:pressed, .choice-box:pressed:hover{ -fx-background-color: #fefefe; -fx-border-color: #eea11e; -fx-border-radius: 3; @@ -121,23 +122,51 @@ // Text color of focused item in the list .choice-box .menu-item:focused > .label { -fx-text-fill: #2d2d2d; } +// -======================== TAB PANE =========================- .tab-pane .tab SVGPath{ - -fx-fill: #2c2c2c; - + -fx-fill: #2c2c2c; // OK +} +.tab-pane .tab:selected SVGPath{ + -fx-fill: #289de8; // OK } .tab-pane .tab{ - -fx-background-color: #fefefe; + -fx-background-color: #fefefe; //ok + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; + -fx-border-radius: 0 0 0 0; + -fx-border-width: 3 0 0 0; + -fx-border-color: #fefefe; //OK } .tab-pane .tab:selected{ - -fx-background-color: #ebebeb; + -fx-background-color: #ebebeb; // OK + -fx-focus-color: transparent; + -fx-faint-focus-color: transparent; + -fx-border-radius: 0 0 0 0; + -fx-border-width: 3 0 0 0; + -fx-border-color: #289de8; // OK } + +.tab-pane > .tab-header-area { + -fx-background-insets: 0.0; + -fx-padding: 5 5 5 5; +} + +.tab-pane > .tab-header-area > .tab-header-background +{ + -fx-background-color: #fefefe; // OK + +} +.tab-pane > .tab-header-area > .headers-region > .tab { + -fx-padding: 10; +} +// -=========================== TABLE ======================- .table-view { -fx-background-color: #fefefe; -fx-background-image: url(app_logo.png); -fx-background-position: center; -fx-background-repeat: no-repeat; - -fx-border-color: #00ffc9; + -fx-border-color: #06b9bb; -fx-border-radius: 3; -fx-border-width: 2; } @@ -146,22 +175,34 @@ } .table-view .column-header-background .label{ -fx-background-color: transparent; - -fx-text-fill: white; + -fx-text-fill: #2c2c2c; } .table-view .column-header-background, .table-view .filler{ -fx-background-color: #fefefe; } -// Remove visible selection 1 -.table-row-cell:filled:selected { - -fx-background: -fx-control-inner-background ; - -fx-background-color: -fx-table-cell-border-color, -fx-background ; - -fx-background-insets: 0, 0 0 1 0 ; - -fx-table-cell-border-color: derive(-fx-color, 5%); + +.table-view .table-cell{ + -fx-text-fill: #2c2c2c; } -// Remove visible selection 2 -.table-row-cell:odd:filled:selected { - -fx-background: -fx-control-inner-background-alt ; +.table-row-cell, .table-row-cell:filled:selected, .table-row-cell:selected{ + -fx-background-color: -fx-table-cell-border-color, #d3fffd; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0.0em; /* 0 */ + -fx-table-cell-border-color: #2c2c2c; } + +.table-row-cell:odd, .table-row-cell:odd:filled:selected, .table-row-cell:odd:selected{ + -fx-background-color: -fx-table-cell-border-color, #fefefe; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0.0em; /* 0 */ + -fx-table-cell-border-color: #2c2c2c; +} + + + + + + .regionUpload{ -fx-shape: "M8,21V19H16V21H8M8,17V15H16V17H8M8,13V11H16V13H8M19,9H5L12,2L19,9Z"; -fx-background-color: #a2e019;