Titlekeys support implemented in Preferences and Setting classes

master
Dmitry Isaenko 2019-05-22 03:50:43 +03:00
parent a5004a9a31
commit bc2764b123
6 changed files with 235 additions and 18 deletions

View File

@ -1,6 +1,5 @@
package konogonka;
import java.util.HashMap;
import java.util.prefs.Preferences;
public class AppPreferences {
@ -8,8 +7,12 @@ public class AppPreferences {
public static AppPreferences getInstance() { return INSTANCE; }
private Preferences preferences;
private int titleKeysCount;
private AppPreferences(){ preferences = Preferences.userRoot().node("konogonka"); }
private AppPreferences(){
preferences = Preferences.userRoot().node("konogonka");
titleKeysCount = getTitleKeysCount();
}
public void setAll(
String xciHeaderKey,
@ -98,11 +101,25 @@ public class AppPreferences {
public String getSystemKey(int number){ return preferences.get("key_area_key_system_0"+number, "");}
public void setSystemKey(int number, String key){ preferences.put("key_area_key_system_0"+number, key); }
public int getTitleKeysCount(){ return preferences.getInt("title_keys_count", 0);}
public void setTitleKeysCount(int number){ preferences.putInt("title_keys_count", number);}
public String[] getTitleKey(int number){
return preferences.get(Integer.toString(number), "0 = 0").split(" = ", 2);
public int getTitleKeysCount(){
return preferences.getInt("title_keys_count", 0);
}
public void setTitleKey(int number, String name, String value){ preferences.put(Integer.toString(number), name+" = "+value); }
// Since we don't want to store title keys that are no longer in use, we have to (try to) remove them.
// This part of code works as a charm. Don't touch.
public void setTitleKeysCount(int number){
if (this.titleKeysCount > number){
for (int i = number; i < this.titleKeysCount; i++) {
preferences.remove("title_key_"+i);
}
}
preferences.putInt("title_keys_count", number);
this.titleKeysCount = number;
}
public String[] getTitleKeyPair(int number){
return preferences.get("title_key_"+number, "0 = 0").split(" = ", 2);
}
public void setTitleKey(int number, String pair){ preferences.put("title_key_"+number, pair); }
}

View File

@ -82,6 +82,11 @@ public class NCAController implements TabController {
keysMap.put("key_area_key_system_0"+i, AppPreferences.getInstance().getSystemKey(i));
// TODO: Add titlekeys
}
for (int i = 0; i < AppPreferences.getInstance().getTitleKeysCount(); i++){
String[] pair = AppPreferences.getInstance().getTitleKeyPair(i);
if ( ! pair[0].equals("0") && ! pair[1].equals("0"))
keysMap.put(pair[0], pair[1]);
}
AnalyzerNCA analyzerNCA = new AnalyzerNCA(file, keysMap);
analyzerNCA.setOnSucceeded(e->{

View File

@ -0,0 +1,113 @@
package konogonka.Settings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.input.KeyEvent;
import konogonka.ServiceWindow;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.ResourceBundle;
public class ListSelectorController implements Initializable {
@FXML
private ListView<String> listView;
@FXML
private TextField newRecordName, newRecordValue;
private ObservableList<String> observableList;
private int mandatoryValueLength;
private String predictionPattern;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
observableList = FXCollections.observableArrayList();
listView.setItems(observableList);
newRecordValue.setTextFormatter(new TextFormatter<Object>(change -> {
if (change.getControlNewText().matches("^[a-fA-F0-9]+$") || change.getControlNewText().isEmpty())
return change;
return null;
}));
}
public void initSelector(int length, String predictionPattern){
this.mandatoryValueLength = length;
if (predictionPattern == null){ // If we need no validation, restrict only spaces/tabs adding
newRecordName.setTextFormatter(new TextFormatter<Object>(change -> {
if (change.getControlNewText().contains(" ") || change.getControlNewText().contains("\t"))
return null;
return change;
}));
}
else { // Otherwise use pattern as name of key + 2 dec numbers
this.predictionPattern = predictionPattern;
newRecordName.setText(predictionPattern);
newRecordName.setTextFormatter(new TextFormatter<Object>(change -> {
if (change.getControlNewText().matches("^"+predictionPattern+"[0-9]{0,2}$"))
return change;
return null;
}));
}
}
/**
* Must be run on start
* Set list content
*/
void setList(HashMap<String, String> stringPairsArray){
if (stringPairsArray != null && ! stringPairsArray.isEmpty())
for (String name: stringPairsArray.keySet())
validateAndAdd(name+" = "+stringPairsArray.get(name));
}
/**
* Return list content
* */
String[] getList(){
return Arrays.copyOf(observableList.toArray(), observableList.toArray().length, String[].class);
}
@FXML
private void listKeyPressed(KeyEvent event){
if (event.getCode().toString().equals("DELETE"))
removeRecord();
}
@FXML
private void removeRecord(){ observableList.remove(listView.getSelectionModel().getSelectedItem()); }
@FXML
private void addNewRecord(){
if (newRecordValue.getText().length() == mandatoryValueLength && ! newRecordName.getText().isEmpty()) {
if (predictionPattern == null) {
validateAndAdd(newRecordName.getText() + " = " + newRecordValue.getText());
newRecordName.clear();
newRecordValue.clear();
}
else {
if (newRecordName.getText().matches("^"+predictionPattern+"[0-9]{2}$")){
validateAndAdd(newRecordName.getText() + " = " + newRecordValue.getText());
newRecordName.setText(predictionPattern);
newRecordValue.clear();
}
else
ServiceWindow.getErrorNotification("Error", "Value name should be: '"+predictionPattern+"XX' where XX are two decimal numbers.");
}
}
else {
ServiceWindow.getErrorNotification("Error", "One of the fields empty or value leigh is incorrect.");
}
}
private void validateAndAdd(String addingItem){
if (!observableList.contains(addingItem)) {
observableList.add(addingItem);
}
}
}

View File

@ -5,7 +5,6 @@ import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import konogonka.AppPreferences;
@ -19,8 +18,10 @@ import java.util.ResourceBundle;
public class SettingsController implements Initializable {
@FXML
private Button okBtn, cancelBtn, importKeysBtn, importTitleKeysBtn;
@FXML
private VBox titleKeysVbox;
ListSelectorController ListSelectorTitleKeysController;
@FXML
private TextField
xciHdrKeyTF,
@ -52,6 +53,17 @@ public class SettingsController implements Initializable {
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
ListSelectorTitleKeysController.initSelector(32, null); // 32 required
HashMap<String, String> preparedPairsMapInit = new HashMap<>();
for (int i = 0; i < AppPreferences.getInstance().getTitleKeysCount(); i++){
preparedPairsMapInit.put(
AppPreferences.getInstance().getTitleKeyPair(i)[0],
AppPreferences.getInstance().getTitleKeyPair(i)[1]
);
}
ListSelectorTitleKeysController.setList(preparedPairsMapInit);
xciHdrKeyTF.setText(AppPreferences.getInstance().getXciHeaderKey());
hdrKeyTF.setText(AppPreferences.getInstance().getHeaderKey());
keyApp0TF.setText(AppPreferences.getInstance().getApplicationKey(0));
@ -157,12 +169,37 @@ public class SettingsController implements Initializable {
catch (IOException ioe){
ioe.printStackTrace();
}
/*
for (String key: fileMap.keySet()){
System.out.print(key+ " - ");
System.out.println(fileMap.get(key));
}
});
importTitleKeysBtn.setOnAction(e->{
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("title.keys");
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("title.keys", "title.keys"));
File prodKeysFile = fileChooser.showOpenDialog(importKeysBtn.getScene().getWindow());
if (prodKeysFile != null && prodKeysFile.exists()) {
try {
BufferedReader br = new BufferedReader(
new FileReader(prodKeysFile)
);
String fileLine;
String[] keyValue;
HashMap<String, String> preparedPairsMap = new HashMap<>();
while ((fileLine = br.readLine()) != null){
keyValue = fileLine.trim().split("\\s+?=\\s+?", 2);
if (keyValue.length == 2 && keyValue[0].length() == 32 && keyValue[1].length() == 32){
preparedPairsMap.put(keyValue[0], keyValue[1]);
}
}
ListSelectorTitleKeysController.setList(preparedPairsMap);
}
catch (IOException ioe){
ioe.printStackTrace();
}
//*/
}
});
@ -201,16 +238,21 @@ public class SettingsController implements Initializable {
keySys6TF.getText(),
keySys7TF.getText()
);
String[] titleKeysSet = ListSelectorTitleKeysController.getList();
if (titleKeysSet != null){
AppPreferences.getInstance().setTitleKeysCount(titleKeysSet.length);
for (int i = 0; i < titleKeysSet.length; i++)
AppPreferences.getInstance().setTitleKey(i, titleKeysSet[i]);
}
thisStage.close();
});
}
private void setTextValidation(TextField tf){
tf.setTextFormatter(new TextFormatter<Object>(change -> {
if (change.getControlNewText().contains(" ") | change.getControlNewText().contains("\t"))
if (change.getControlNewText().contains(" ") || change.getControlNewText().contains("\t"))
return null;
else
return change;
return change;
}));
}
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.SVGPath?>
<VBox spacing="5.0" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="konogonka.Settings.ListSelectorController">
<children>
<HBox alignment="CENTER_LEFT" spacing="5.0" VBox.vgrow="ALWAYS">
<children>
<ListView fx:id="listView" onKeyPressed="#listKeyPressed" prefWidth="200.0" HBox.hgrow="ALWAYS" />
<VBox spacing="5.0">
<children>
<Button mnemonicParsing="false" onAction="#removeRecord">
<graphic>
<SVGPath content="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="#cc0101" />
</graphic>
</Button>
</children>
</VBox>
</children>
</HBox>
<HBox spacing="5.0" VBox.vgrow="NEVER">
<children>
<TextField fx:id="newRecordName" HBox.hgrow="ALWAYS" />
<Label text="=" />
<TextField fx:id="newRecordValue" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" onAction="#addNewRecord">
<graphic>
<SVGPath content="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" fill="#007f08" />
</graphic>
</Button>
</children>
</HBox>
</children>
</VBox>

View File

@ -224,7 +224,7 @@
<SVGPath content="M1,12H10.76L8.26,9.5L9.67,8.08L14.59,13L9.67,17.92L8.26,16.5L10.76,14H1V12M19,3C20.11,3 21,3.9 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V16H5V19H19V7H5V10H3V5A2,2 0 0,1 5,3H19Z" />
</graphic>
</Button>
<VBox fx:id="titleKeysVbox" spacing="5.0" />
<fx:include fx:id="ListSelectorTitleKeys" source="ListSelectorLayout.fxml" />
</children>
</VBox>
</content>