This commit is contained in:
Dmitry Isaenko 2019-02-18 03:06:49 +03:00
parent c4d0959cf3
commit f5a9ddf8df
13 changed files with 162 additions and 91 deletions

View file

@ -34,7 +34,7 @@ Install JRE/JDK 8 or higher (openJDK is good. Oracle's one is also good). JavaFX
See 'Linux' section. See 'Linux' section.
Set 'Security & Privacy' if needed. Set 'Security & Privacy' settings if needed.
### Windows: ### Windows:
@ -63,10 +63,18 @@ Table 'Status' = 'Uploaded' does not means that file installed. It means that it
Handling successful/failed installation is a purpose of the other side application (TinFoil/GoldLeaf). (And they don't provide any feedback interfaces so I can't detect success/failure.) Handling successful/failed installation is a purpose of the other side application (TinFoil/GoldLeaf). (And they don't provide any feedback interfaces so I can't detect success/failure.)
## TODO: ## TODO:
- [x] macOS QA by [Konstanin Kelemen](https://github.com/konstantin-kelemen). Appreciate assistance of [Vitaliy Natarov](https://github.com/SebastianUA). - [x] macOS QA
-[x] v0.1
-[ ] v0.2 (partly)
- [x] Windows support - [x] Windows support
- [ ] code refactoring - [ ] code refactoring (almost. todo: printLog() )
- [ ] GoldLeaf support - [x] GoldLeaf support
- [ ] XCI support - [ ] XCI support
- [ ] Settings
- [ ] File order sort (non-critical) - [ ] File order sort (non-critical)
## Thanks
Appreciate assistance and support of both Vitaliy and Konstantin. Without you all this magic would not have happened.
[Konstanin Kelemen](https://github.com/konstantin-kelemen)
[Vitaliy Natarov](https://github.com/SebastianUA)

View file

@ -0,0 +1,23 @@
package nsusbloader;
import java.util.prefs.Preferences;
public class AppPreferences {
private static final AppPreferences INSTANCE = new AppPreferences();
public static AppPreferences getInstance() { return INSTANCE; }
private Preferences preferences;
private AppPreferences(){ preferences = Preferences.userRoot().node("NS-USBloader"); }
public String getTheme(){
String theme = preferences.get("THEME", "/res/app_dark.css"); // Don't let user to change settings manually
if (!theme.matches("(^/res/app_dark.css$)|(^/res/app_light.css$)"))
theme = "/res/app_dark.css";
return theme;
}
public void setTheme(String theme){ preferences.put("THEME", theme); }
public String getRecent(){ return preferences.get("RECENT", System.getProperty("user.home")); }
public void setRecent(String path){ preferences.put("RECENT", path); }
}

View file

@ -1,4 +1,4 @@
package nsusbloader; package nsusbloader.Controllers;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -8,7 +8,10 @@ import javafx.scene.control.*;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.Controllers.NSTableViewController; import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl;
import nsusbloader.NSLMain;
import nsusbloader.UsbCommunications;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
@ -46,7 +49,7 @@ public class NSLMainController implements Initializable {
@Override @Override
public void initialize(URL url, ResourceBundle rb) { public void initialize(URL url, ResourceBundle rb) {
this.resourceBundle = rb; this.resourceBundle = rb;
logArea.setText(rb.getString("logsGreetingsMessage")+" "+NSLMain.appVersion+"!\n"); logArea.setText(rb.getString("logsGreetingsMessage")+" "+ NSLMain.appVersion+"!\n");
if (System.getProperty("os.name").toLowerCase().startsWith("lin")) if (System.getProperty("os.name").toLowerCase().startsWith("lin"))
if (!System.getProperty("user.name").equals("root")) 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("logsEnteredAsMsg1")+System.getProperty("user.name")+"\n"+rb.getString("logsEnteredAsMsg2") + "\n");
@ -81,18 +84,20 @@ public class NSLMainController implements Initializable {
btnSwitchImage.getStyleClass().add("regionLamp"); btnSwitchImage.getStyleClass().add("regionLamp");
switchThemeBtn.setGraphic(btnSwitchImage); switchThemeBtn.setGraphic(btnSwitchImage);
this.switchThemeBtn.setOnAction(e->switchTheme()); this.switchThemeBtn.setOnAction(e->switchTheme());
previouslyOpenedPath = AppPreferences.getInstance().getRecent();
} }
/** /**
* Changes UI theme on the go * Changes UI theme on the go
* */ * */
private void switchTheme(){ private void switchTheme(){
if (switchThemeBtn.getScene().getStylesheets().get(0).equals("/res/app.css")) { if (switchThemeBtn.getScene().getStylesheets().get(0).equals("/res/app_dark.css")) {
switchThemeBtn.getScene().getStylesheets().remove("/res/app.css"); switchThemeBtn.getScene().getStylesheets().remove("/res/app_dark.css");
switchThemeBtn.getScene().getStylesheets().add("/res/app_light.css"); switchThemeBtn.getScene().getStylesheets().add("/res/app_light.css");
} }
else { else {
switchThemeBtn.getScene().getStylesheets().add("/res/app.css");
switchThemeBtn.getScene().getStylesheets().remove("/res/app_light.css"); switchThemeBtn.getScene().getStylesheets().remove("/res/app_light.css");
switchThemeBtn.getScene().getStylesheets().add("/res/app_dark.css");
} }
} }
/** /**
@ -103,16 +108,14 @@ public class NSLMainController implements Initializable {
List<File> filesList; List<File> filesList;
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("btnFileOpen")); fileChooser.setTitle(resourceBundle.getString("btnFileOpen"));
if (previouslyOpenedPath == null)
File validator = new File(previouslyOpenedPath);
if (validator.exists())
fileChooser.setInitialDirectory(validator); // TODO: read from prefs
else
fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: read from prefs fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: read from prefs
else {
File validator = new File(previouslyOpenedPath); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NSP ROM", "*.nsp"));
if (validator.exists())
fileChooser.setInitialDirectory(validator); // TODO: read from prefs
else
fileChooser.setInitialDirectory(new File(System.getProperty("user.home"))); // TODO: read from prefs
}
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("NS ROM", "*.nsp"));
filesList = fileChooser.showOpenMultipleDialog(logArea.getScene().getWindow()); filesList = fileChooser.showOpenMultipleDialog(logArea.getScene().getWindow());
if (filesList != null && !filesList.isEmpty()) { if (filesList != null && !filesList.isEmpty()) {
@ -156,7 +159,7 @@ public class NSLMainController implements Initializable {
* This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission" * This thing modify UI for reusing 'Upload to NS' button and make functionality set for "Stop transmission"
* Called from mediator * Called from mediator
* */ * */
void notifyTransmissionStarted(boolean isTransmissionStarted){ public void notifyTransmissionStarted(boolean isTransmissionStarted){
if (isTransmissionStarted) { if (isTransmissionStarted) {
selectNspBtn.setDisable(true); selectNspBtn.setDisable(true);
uploadStopBtn.setOnAction(e->{ stopBtnAction(); }); uploadStopBtn.setOnAction(e->{ stopBtnAction(); });
@ -182,4 +185,11 @@ public class NSLMainController implements Initializable {
uploadStopBtn.getStyleClass().add("buttonUp"); uploadStopBtn.getStyleClass().add("buttonUp");
} }
} }
/**
* Save preferences before exit
* */
public void exit(){
AppPreferences.getInstance().setTheme(switchThemeBtn.getScene().getStylesheets().get(0));
AppPreferences.getInstance().setRecent(previouslyOpenedPath);
}
} }

View file

@ -39,14 +39,14 @@ public class NSLRowModel {
public void setStatus(EFileStatus status){ // TODO: Localization public void setStatus(EFileStatus status){ // TODO: Localization
switch (status){ switch (status){
case UPLOADED: case UPLOADED:
this.status = "Uploaded"; this.status = "Success";
markForUpload = false; markForUpload = false;
break; break;
case FAILED: case FAILED:
this.status = "Upload failed"; this.status = "Failed";
break; break;
case INCORRECT_FILE_FAILED: case INCORRECT_FILE_FAILED:
this.status = "File incorrect"; this.status = "Failed: Incorrect file";
markForUpload = false; markForUpload = false;
break; break;
} }

View file

@ -33,15 +33,29 @@ public class NSTableViewController implements Initializable {
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
rowsObsLst = FXCollections.observableArrayList(); rowsObsLst = FXCollections.observableArrayList();
table.setPlaceholder(new Label()); table.setPlaceholder(new Label());
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TableColumn<NSLRowModel, String> statusColumn = new TableColumn<>(resourceBundle.getString("tableStatusLbl")); TableColumn<NSLRowModel, String> statusColumn = new TableColumn<>(resourceBundle.getString("tableStatusLbl"));
TableColumn<NSLRowModel, String> fileNameColumn = new TableColumn<>(resourceBundle.getString("tableFileNameLbl")); TableColumn<NSLRowModel, String> fileNameColumn = new TableColumn<>(resourceBundle.getString("tableFileNameLbl"));
TableColumn<NSLRowModel, String> fileSizeColumn = new TableColumn<>(resourceBundle.getString("tableSizeLbl")); TableColumn<NSLRowModel, String> fileSizeColumn = new TableColumn<>(resourceBundle.getString("tableSizeLbl"));
TableColumn<NSLRowModel, Boolean> uploadColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl")); TableColumn<NSLRowModel, Boolean> uploadColumn = new TableColumn<>(resourceBundle.getString("tableUploadLbl"));
statusColumn.setMinWidth(70.0); // See https://bugs.openjdk.java.net/browse/JDK-8157687
fileNameColumn.setMinWidth(250.0); statusColumn.setMinWidth(100.0);
fileSizeColumn.setMinWidth(70.0); statusColumn.setPrefWidth(100.0);
uploadColumn.setMinWidth(70.0); statusColumn.setMaxWidth(100.0);
statusColumn.setResizable(false);
fileNameColumn.setMinWidth(25.0);
fileSizeColumn.setMinWidth(120.0);
fileSizeColumn.setPrefWidth(120.0);
fileSizeColumn.setMaxWidth(120.0);
fileSizeColumn.setResizable(false);
uploadColumn.setMinWidth(100.0);
uploadColumn.setPrefWidth(100.0);
uploadColumn.setMaxWidth(100.0);
uploadColumn.setResizable(false);
statusColumn.setCellValueFactory(new PropertyValueFactory<>("status")); statusColumn.setCellValueFactory(new PropertyValueFactory<>("status"));
fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("nspFileName")); fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("nspFileName"));
@ -76,12 +90,6 @@ public class NSTableViewController implements Initializable {
table.setItems(rowsObsLst); table.setItems(rowsObsLst);
table.getColumns().addAll(statusColumn, fileNameColumn, fileSizeColumn, uploadColumn); 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/стихи_2"), false));
rowsObsLst.add(new NSLRowModel(new File("/home/loper/стихи_2"), true));
*/
} }
/** /**
* See uploadColumn callback. In case of GoldLeaf we have to restrict selection * See uploadColumn callback. In case of GoldLeaf we have to restrict selection
@ -145,6 +153,7 @@ public class NSTableViewController implements Initializable {
model.setStatus(status); model.setStatus(status);
} }
} }
table.refresh();
} }
/** /**
* Called if selected different USB protocol * Called if selected different USB protocol

View file

@ -1,26 +1,28 @@
package nsusbloader; package nsusbloader;
import nsusbloader.Controllers.NSLMainController;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
class MediatorControl { public class MediatorControl {
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
private NSLMainController applicationController; private NSLMainController applicationController;
static MediatorControl getInstance(){ public static MediatorControl getInstance(){
return MediatorControlHold.INSTANCE; return MediatorControlHold.INSTANCE;
} }
private static class MediatorControlHold { private static class MediatorControlHold {
private static final MediatorControl INSTANCE = new MediatorControl(); private static final MediatorControl INSTANCE = new MediatorControl();
} }
void setController(NSLMainController controller){ public void setController(NSLMainController controller){
this.applicationController = controller; this.applicationController = controller;
} }
NSLMainController getContoller(){ return this.applicationController; } NSLMainController getContoller(){ return this.applicationController; }
synchronized void setTransferActive(boolean state) { public synchronized void setTransferActive(boolean state) {
isTransferActive.set(state); isTransferActive.set(state);
applicationController.notifyTransmissionStarted(state); applicationController.notifyTransmissionStarted(state);
} }
synchronized boolean getTransferActive() { return this.isTransferActive.get(); } public synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
} }

View file

@ -49,16 +49,15 @@ public class MessagesConsumer extends AnimationTimer {
if (progressRecieved > 0) if (progressRecieved > 0)
progress.forEach(prg -> progressBar.setProgress(prg)); progress.forEach(prg -> progressBar.setProgress(prg));
if (isInterrupted) { if (isInterrupted) { // It's safe 'cuz it's could't be interrupted while HashMap populating
MediatorControl.getInstance().setTransferActive(false); MediatorControl.getInstance().setTransferActive(false);
progressBar.setProgress(0.0); progressBar.setProgress(0.0);
if (statusMap.size() > 0) // It's safe 'cuz it's could't be interrupted while HashMap populating if (statusMap.size() > 0)
for (String key : statusMap.keySet()) for (String key : statusMap.keySet())
tableViewController.setFileStatus(key, statusMap.get(key)); tableViewController.setFileStatus(key, statusMap.get(key));
this.stop(); this.stop();
} }
//TODO
} }
void interrupt(){ void interrupt(){

View file

@ -6,22 +6,24 @@ import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.stage.Stage; import javafx.stage.Stage;
import nsusbloader.Controllers.NSLMainController;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class NSLMain extends Application { public class NSLMain extends Application {
static final String appVersion = "v0.2-DEVELOPMENT"; public static final String appVersion = "v0.2";
@Override @Override
public void start(Stage primaryStage) throws Exception{ public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));
ResourceBundle rb; ResourceBundle rb;
if (Locale.getDefault().getISO3Language().equals("rus")) if (Locale.getDefault().getISO3Language().equals("rus"))
rb = ResourceBundle.getBundle("locale", new Locale("ru")); rb = ResourceBundle.getBundle("locale", new Locale("ru"));
else else
rb = ResourceBundle.getBundle("locale", new Locale("en")); rb = ResourceBundle.getBundle("locale", new Locale("en"));
FXMLLoader loader = new FXMLLoader(getClass().getResource("/NSLMain.fxml"));
loader.setResources(rb); loader.setResources(rb);
Parent root = loader.load(); Parent root = loader.load();
@ -36,7 +38,9 @@ public class NSLMain extends Application {
primaryStage.setMinWidth(600); primaryStage.setMinWidth(600);
primaryStage.setMinHeight(375); primaryStage.setMinHeight(375);
Scene mainScene = new Scene(root, 800, 400); Scene mainScene = new Scene(root, 800, 400);
mainScene.getStylesheets().add("/res/app.css");
mainScene.getStylesheets().add(AppPreferences.getInstance().getTheme());
primaryStage.setScene(mainScene); primaryStage.setScene(mainScene);
primaryStage.show(); primaryStage.show();
@ -45,6 +49,9 @@ public class NSLMain extends Application {
if(! ServiceWindow.getConfirmationWindow(rb.getString("windowTitleConfirmExit"), rb.getString("windowBodyConfirmExit"))) if(! ServiceWindow.getConfirmationWindow(rb.getString("windowTitleConfirmExit"), rb.getString("windowBodyConfirmExit")))
e.consume(); e.consume();
}); });
NSLMainController controller = loader.getController();
primaryStage.setOnHidden(e-> controller.exit());
} }
public static void main(String[] args) { public static void main(String[] args) {

View file

@ -35,12 +35,9 @@ public class ServiceWindow {
alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinWidth(Region.USE_PREF_SIZE);
alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); alertBox.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really. alertBox.setResizable(true); // Java bug workaround for JDR11/OpenJFX. TODO: nothing. really.
alertBox.getDialogPane().getStylesheets().add("/res/app.css"); alertBox.getDialogPane().getStylesheets().add(AppPreferences.getInstance().getTheme());
Optional<ButtonType> result = alertBox.showAndWait(); Optional<ButtonType> result = alertBox.showAndWait();
if (result.get() == ButtonType.OK)
return true;
else
return false;
return (result.isPresent() && result.get() == ButtonType.OK);
} }
} }

View file

@ -18,12 +18,13 @@ import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
class UsbCommunications extends Task<Void> { public class UsbCommunications extends Task<Void> {
private final int DEFAULT_INTERFACE = 0; private final int DEFAULT_INTERFACE = 0;
private BlockingQueue<String> msgQueue; private BlockingQueue<String> msgQueue;
private BlockingQueue<Double> progressQueue; private BlockingQueue<Double> progressQueue;
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
private EFileStatus status = EFileStatus.FAILED;
private MessagesConsumer msgConsumer; private MessagesConsumer msgConsumer;
@ -44,7 +45,7 @@ class UsbCommunications extends Task<Void> {
Since this application let user an ability (theoretically) to choose same files in different folders, the latest selected file will be added to the list and handled correctly. Since this application let user an ability (theoretically) to choose same files in different folders, the latest selected file will be added to the list and handled correctly.
I have no idea why he/she will make a decision to do that. Just in case, we're good in this point. I have no idea why he/she will make a decision to do that. Just in case, we're good in this point.
*/ */
UsbCommunications(List<File> nspList, String protocol){ public UsbCommunications(List<File> nspList, String protocol){
this.protocol = protocol; this.protocol = protocol;
this.nspMap = new HashMap<>(); this.nspMap = new HashMap<>();
for (File f: nspList) for (File f: nspList)
@ -275,28 +276,17 @@ class UsbCommunications extends Task<Void> {
printLog("\tEnd chain", EMsgType.INFO); printLog("\tEnd chain", EMsgType.INFO);
return null; return null;
} }
/**
* Report transfer status
* */
private void reportTransferStatus(EFileStatus status){
for (String fileName: nspMap.keySet())
statusMap.put(fileName, status);
}
/** /**
* Tinfoil processing * Tinfoil processing
* */ * */
private class TinFoil{ private class TinFoil{
TinFoil(){ TinFoil(){
if (!sendListOfNSP()) { if (!sendListOfNSP())
reportTransferStatus(EFileStatus.FAILED);
return; return;
}
if (proceedCommands()) // REPORT SUCCESS if (proceedCommands()) // REPORT SUCCESS
reportTransferStatus(EFileStatus.UPLOADED); status = EFileStatus.UPLOADED; // Don't change status that is already set to FAILED
else // REPORT FAILURE
reportTransferStatus(EFileStatus.FAILED);
} }
/** /**
* Send what NSP will be transferred * Send what NSP will be transferred
@ -547,15 +537,14 @@ class UsbCommunications extends Task<Void> {
PFSProvider pfsElement = new PFSProvider(nspMap.get(nspMap.keySet().toArray()[0]), msgQueue); PFSProvider pfsElement = new PFSProvider(nspMap.get(nspMap.keySet().toArray()[0]), msgQueue);
if (!pfsElement.init()) { if (!pfsElement.init()) {
printLog("GL File provided have incorrect structure and won't be uploaded", EMsgType.FAIL); printLog("GL File provided have incorrect structure and won't be uploaded", EMsgType.FAIL);
reportTransferStatus(EFileStatus.INCORRECT_FILE_FAILED); status = EFileStatus.INCORRECT_FILE_FAILED;
return; return;
} }
printLog("GL File structure validated and it will be uploaded", EMsgType.PASS); printLog("GL File structure validated and it will be uploaded", EMsgType.PASS);
if (initGoldLeafProtocol(pfsElement)) if (initGoldLeafProtocol(pfsElement))
reportTransferStatus(EFileStatus.UPLOADED); status = EFileStatus.UPLOADED;
else // else - no change status that is already set to FAILED
reportTransferStatus(EFileStatus.FAILED);
} }
private boolean initGoldLeafProtocol(PFSProvider pfsElement){ private boolean initGoldLeafProtocol(PFSProvider pfsElement){
// Go parse commands // Go parse commands
@ -774,6 +763,11 @@ class UsbCommunications extends Task<Void> {
LibUsb.exit(contextNS); LibUsb.exit(contextNS);
printLog("Requested context close", EMsgType.INFO); printLog("Requested context close", EMsgType.INFO);
} }
// Report status
for (String fileName: nspMap.keySet())
statusMap.put(fileName, status);
msgConsumer.interrupt(); msgConsumer.interrupt();
} }
/** /**

View file

@ -17,7 +17,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?> <?import javafx.scene.shape.SVGPath?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.NSLMainController"> <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nsusbloader.Controllers.NSLMainController">
<children> <children>
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children> <children>

View file

@ -98,7 +98,7 @@
-fx-background-color: #f7fafa; -fx-background-color: #f7fafa;
-fx-min-height: 1; -fx-min-height: 1;
} }
// -======================== Choice box =========================-
.choice-box { .choice-box {
-fx-background-color: #4f4f4f; -fx-background-color: #4f4f4f;
-fx-border-color: #4f4f4f; -fx-border-color: #4f4f4f;
@ -120,13 +120,19 @@
} }
// Background color of the whole context menu // Background color of the whole context menu
.choice-box .context-menu { -fx-background-color: #2d2d2d; } .choice-box .context-menu {
-fx-background-color: #2d2d2d;
}
// Focused item background color in the list // Focused item background color in the list
.choice-box .menu-item:focused { -fx-background-color: #eea11e; } .choice-box .context-menu .menu-item:focused {
// Text color of non-focused items in the list -fx-background-color: #eea11e;
.choice-box .menu-item > .label { -fx-text-fill: #f7fafa; }
// Text color of focused item in the list }
.choice-box .menu-item:focused > .label { -fx-text-fill: #2d2d2d; } .choice-box .context-menu .menu-item:focused .label {
-fx-text-fill: #2c2c2c;
}
// -======================== TAB PANE =========================- // -======================== TAB PANE =========================-
.tab-pane .tab SVGPath{ .tab-pane .tab SVGPath{
@ -176,12 +182,18 @@
-fx-border-radius: 3; -fx-border-radius: 3;
-fx-border-width: 2; -fx-border-width: 2;
} }
.table-view .arrow {
-fx-mark-color: #08f3ff ;
}
.table-view .column-header { .table-view .column-header {
-fx-background-color: transparent; -fx-background-color: transparent;
-fx-border-width: 0 1 2 0;
-fx-border-color: #6d8484;
} }
.table-view .column-header-background .label{ .table-view .column-header-background .label{
-fx-background-color: transparent; -fx-background-color: transparent;
-fx-text-fill: #08f3ff; -fx-text-fill: #08f3ff;
} }
.table-view .column-header-background, .table-view .filler{ .table-view .column-header-background, .table-view .filler{
-fx-background-color: #4f4f4f; -fx-background-color: #4f4f4f;
@ -194,14 +206,14 @@
-fx-background-color: -fx-table-cell-border-color, #424242; -fx-background-color: -fx-table-cell-border-color, #424242;
-fx-background-insets: 0, 0 0 1 0; -fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */ -fx-padding: 0.0em; /* 0 */
-fx-table-cell-border-color: #f7fafa; -fx-table-cell-border-color: #6d8484;
} }
.table-row-cell:odd, .table-row-cell:odd:filled:selected, .table-row-cell:odd:selected{ .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-color: -fx-table-cell-border-color, #4f4f4f;
-fx-background-insets: 0, 0 0 1 0; -fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */ -fx-padding: 0.0em; /* 0 */
-fx-table-cell-border-color: #f7fafa; -fx-table-cell-border-color: #6d8484;
} }
// -========================== Context menu =====================- // -========================== Context menu =====================-
.context-menu { .context-menu {

View file

@ -99,7 +99,7 @@
-fx-background-color: #2c2c2c; -fx-background-color: #2c2c2c;
-fx-min-height: 1; -fx-min-height: 1;
} }
// -======================== Choice box =========================-
.choice-box { .choice-box {
-fx-background-color: #fefefe; -fx-background-color: #fefefe;
-fx-border-color: #fefefe; -fx-border-color: #fefefe;
@ -121,13 +121,18 @@
} }
// Background color of the whole context menu // Background color of the whole context menu
.choice-box .context-menu { -fx-background-color: #fefefe; } .choice-box .context-menu {
-fx-background-color: #fefefe;
}
// Focused item background color in the list // Focused item background color in the list
.choice-box .menu-item:focused { -fx-background-color: #eea11e; } .choice-box .context-menu .menu-item:focused {
// Text color of non-focused items in the list -fx-background-color: #eea11e;
.choice-box .menu-item > .label { -fx-text-fill: #2c2c2c; }
// Text color of focused item in the list }
.choice-box .menu-item:focused > .label { -fx-text-fill: #2d2d2d; } .choice-box .context-menu .menu-item:focused .label {
-fx-text-fill: #2c2c2c;
}
// -======================== TAB PANE =========================- // -======================== TAB PANE =========================-
.tab-pane .tab SVGPath{ .tab-pane .tab SVGPath{
@ -177,8 +182,13 @@
-fx-border-radius: 3; -fx-border-radius: 3;
-fx-border-width: 2; -fx-border-width: 2;
} }
.table-view .arrow {
-fx-mark-color: #2c2c2c ;
}
.table-view .column-header { .table-view .column-header {
-fx-background-color: transparent; -fx-background-color: transparent;
-fx-border-width: 0 1 2 0;
-fx-border-color: #b0b0b0;
} }
.table-view .column-header-background .label{ .table-view .column-header-background .label{
-fx-background-color: transparent; -fx-background-color: transparent;
@ -195,14 +205,14 @@
-fx-background-color: -fx-table-cell-border-color, #d3fffd; -fx-background-color: -fx-table-cell-border-color, #d3fffd;
-fx-background-insets: 0, 0 0 1 0; -fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */ -fx-padding: 0.0em; /* 0 */
-fx-table-cell-border-color: #2c2c2c; -fx-table-cell-border-color: #b0b0b0;
} }
.table-row-cell:odd, .table-row-cell:odd:filled:selected, .table-row-cell:odd:selected{ .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-color: -fx-table-cell-border-color, #fefefe;
-fx-background-insets: 0, 0 0 1 0; -fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */ -fx-padding: 0.0em; /* 0 */
-fx-table-cell-border-color: #2c2c2c; -fx-table-cell-border-color: #b0b0b0;
} }
// -========================== Context menu =====================- // -========================== Context menu =====================-
.context-menu { .context-menu {