commit a39aaca33ec884a86238089bcafb64f3bc23bad1 Author: Carlos Galindo Date: Sun Jun 12 00:20:11 2016 +0200 Initial commit diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..5af7f30 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_code_gson_gson_2_6_2.xml b/.idea/libraries/Maven__com_google_code_gson_gson_2_6_2.xml new file mode 100644 index 0000000..85823a2 --- /dev/null +++ b/.idea/libraries/Maven__com_google_code_gson_gson_2_6_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_jfoenix_jfoenix_0_0_0_SNAPSHOT.xml b/.idea/libraries/Maven__com_jfoenix_jfoenix_0_0_0_SNAPSHOT.xml new file mode 100644 index 0000000..48e0dee --- /dev/null +++ b/.idea/libraries/Maven__com_jfoenix_jfoenix_0_0_0_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__junit_junit_3_8_1.xml b/.idea/libraries/Maven__junit_junit_3_8_1.xml new file mode 100644 index 0000000..71b2993 --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_3_8_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dfca8c4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4add186 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/jstudy.iml b/jstudy.iml new file mode 100644 index 0000000..3f2b906 --- /dev/null +++ b/jstudy.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..07991d6 --- /dev/null +++ b/pom.xml @@ -0,0 +1,74 @@ + + 4.0.0 + es.kauron.jstudy + jstudy + jar + 0.2 + + + + jitpack.io + https://jitpack.io + + + Maven Snapshots + https://oss.sonatype.org/content/groups/public + + + + jstudy + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + com.jfoenix + jfoenix + 0.0.0-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.6 + + + package + + single + + + + + + + true + es.kauron.jstudy.Main + + + . + + + + jar-with-dependencies + + + + + + diff --git a/src/main/java/es/kauron/jstudy/Main.java b/src/main/java/es/kauron/jstudy/Main.java new file mode 100644 index 0000000..d3dc041 --- /dev/null +++ b/src/main/java/es/kauron/jstudy/Main.java @@ -0,0 +1,23 @@ +package es.kauron.jstudy; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) throws Exception{ + Parent root = FXMLLoader.load(Main.class.getResource("view/main.fxml")); + primaryStage.setTitle("JStudy"); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } + + + public static void main(String[] args) { + launch(args); + } +} diff --git a/src/main/java/es/kauron/jstudy/controller/Controller.java b/src/main/java/es/kauron/jstudy/controller/Controller.java new file mode 100644 index 0000000..cc2ee5e --- /dev/null +++ b/src/main/java/es/kauron/jstudy/controller/Controller.java @@ -0,0 +1,113 @@ +package es.kauron.jstudy.controller; + +import es.kauron.jstudy.Main; +import es.kauron.jstudy.model.TestItem; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Parent; +import javafx.scene.control.*; +import javafx.scene.layout.BorderPane; +import javafx.stage.FileChooser; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.*; + +public class Controller implements Initializable { + @FXML + private TabPane tabPane; + + @FXML + private BorderPane root; + @FXML + private ToolBar toolbar; + @FXML + private MenuItem saveMenu; + + @FXML + private CheckMenuItem caseMenu; + @FXML + private RadioMenuItem allMenu, selectedMenu; + + private BooleanProperty table = new SimpleBooleanProperty(false); + private Map tabMap = new HashMap<>(); + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + tabPane.getSelectionModel().selectedItemProperty().addListener((change, o, n) -> { + if (n.getContent().getId() != null) { + table.set(true); + root.getTop().autosize(); + } + }); + saveMenu.disableProperty().bind(table.not()); + } + + @FXML + private void onNewAction(ActionEvent event) { + TextInputDialog dialog = new TextInputDialog("Name"); + dialog.showAndWait(); + tabPane.getTabs().add(createTableTab(dialog.getResult(), new ArrayList<>())); + tabPane.getSelectionModel().selectLast(); + } + + @FXML + private void onLoadAction(ActionEvent event) { + FileChooser chooser = new FileChooser(); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JStudy file", "*.jsdb")); + File file = chooser.showOpenDialog(root.getScene().getWindow()); + if (file == null) return; + List aux = TestItem.loadFrom(file); + if (aux != null) { + tabPane.getTabs().add(createTableTab(file.getName().substring(0, file.getName().lastIndexOf('.')), aux)); + tabPane.getSelectionModel().selectLast(); + } + } + + @FXML + private void onSaveAction(ActionEvent event) { + FileChooser chooser = new FileChooser(); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JStudy file", "*.jsdb")); + File file = chooser.showSaveDialog(root.getScene().getWindow()); + if (file == null) return; + TestItem.saveTo(file, tabMap.get(tabPane.getSelectionModel().getSelectedItem()).getData()); + } + + private Tab createTableTab(String name, List list) { + try { + Tab tab = new Tab(name); + tab.setId("table" + tab.hashCode()); + + FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/table.fxml")); + Parent tableRoot = loader.load(); + + ((TableController) loader.getController()).setData(list, this); + tabMap.put(tab, loader.getController()); + + tab.setContent(tableRoot); + return tab; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + void newTest(List list) { + try { + FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/test.fxml")); + Parent root = loader.load(); + + ((TestController) loader.getController()).setList(new ArrayList<>(list)); + + tabPane.getTabs().add(new Tab("Test: " + tabPane.getSelectionModel().getSelectedItem().getText(), root)); + tabPane.getSelectionModel().selectLast(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/es/kauron/jstudy/controller/EditController.java b/src/main/java/es/kauron/jstudy/controller/EditController.java new file mode 100644 index 0000000..27b3c73 --- /dev/null +++ b/src/main/java/es/kauron/jstudy/controller/EditController.java @@ -0,0 +1,63 @@ +package es.kauron.jstudy.controller; + +import es.kauron.jstudy.model.TestItem; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.TextField; +import javafx.stage.Stage; + +import java.net.URL; +import java.util.ResourceBundle; + +public class EditController implements Initializable { + @FXML + private TextField questionText, answerText; + private ObservableList list; + private int index; + private TestItem item; + + @Override + public void initialize(URL url, ResourceBundle rb) { + } + + protected void setList(ObservableList list) { + setList(list, -1); + } + + protected void setList(ObservableList list, int index) { + this.list = list; // Save attributes correctly + this.index = index; + // Copy current values to textViews + // and initialize item to hold the current object in edition + if (index < 0) item = new TestItem("",""); + else { + questionText.setText(list.get(index).getQuestion()); + answerText.setText(list.get(index).getAnswer()); + item = new TestItem(list.get(index)); + } + item.questionProperty().bind(questionText.textProperty()); + item.answerProperty().bind(answerText.textProperty()); + } + + @FXML + private void onSaveAction(ActionEvent event) { + if (index < 0) { + if (!item.isValid()) + return; + list.add(item); + } else { + list.set(index, item); + } + onCancelAction(event); + } + + @FXML + private void onCancelAction(ActionEvent event) { + ((Stage) ((Node) event.getSource()) + .getScene().getWindow()) + .close(); + } +} diff --git a/src/main/java/es/kauron/jstudy/controller/TableController.java b/src/main/java/es/kauron/jstudy/controller/TableController.java new file mode 100644 index 0000000..8030a56 --- /dev/null +++ b/src/main/java/es/kauron/jstudy/controller/TableController.java @@ -0,0 +1,121 @@ +package es.kauron.jstudy.controller; + +import es.kauron.jstudy.Main; +import es.kauron.jstudy.model.TestItem; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.stage.Modality; +import javafx.stage.Stage; + +import java.io.IOException; +import java.net.URL; +import java.util.List; +import java.util.ResourceBundle; + +public class TableController implements Initializable { + @FXML + private TableView table; + @FXML + private TableColumn answerCol, questionCol; + @FXML + private Button editButton, duplicateButton, swapButton, testSelectionButton, deleteButton; + + private ObservableList data; + private Controller parent; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + answerCol.setCellValueFactory(e -> e.getValue().answerProperty()); + questionCol.setCellValueFactory(e -> e.getValue().questionProperty()); + editButton.disableProperty().bind(table.getSelectionModel().selectedIndexProperty().lessThan(0)); + swapButton.disableProperty().bind(table.getSelectionModel().selectedIndexProperty().lessThan(0)); + deleteButton.disableProperty().bind(table.getSelectionModel().selectedIndexProperty().lessThan(0)); + duplicateButton.disableProperty().bind(table.getSelectionModel().selectedIndexProperty().lessThan(0)); + testSelectionButton.disableProperty().bind(table.getSelectionModel().selectedIndexProperty().lessThan(0)); + } + + void setData(List list, Controller controller) { + this.data = FXCollections.observableArrayList(list); + this.parent = controller; + table.setItems(data); + } + + List getData() {return data;} + + @FXML + private void onAddAction(ActionEvent event) { + try { + FXMLLoader cargador = new FXMLLoader(Main.class.getResource("view/edit.fxml")); + Parent pRoot = cargador.load(); + + ((EditController) cargador.getController()).setList(data); + + Stage stage = new Stage(); + stage.setTitle("New entry"); + stage.setScene(new Scene(pRoot)); + stage.initModality(Modality.APPLICATION_MODAL); + stage.showAndWait(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @FXML + private void onEditAction(ActionEvent event) { + ObservableList list = table.getSelectionModel().getSelectedIndices(); + if (list.size() != 1) return; + int index = list.get(0); + try { + FXMLLoader cargador = new FXMLLoader(Main.class.getResource("view/edit.fxml")); + Parent root = cargador.load(); + + ((EditController) cargador.getController()).setList(table.getItems(), index); + + Stage stage = new Stage(); + stage.setTitle("Editing entry..."); + stage.setScene(new Scene(root)); + stage.initModality(Modality.APPLICATION_MODAL); + stage.showAndWait(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @FXML + private void onSwapAction(ActionEvent event) { + for (TestItem item : table.getSelectionModel().getSelectedItems()) { + String question = item.getQuestion(); + item.questionProperty().set(item.getAnswer()); + item.answerProperty().set(question); + } + } + + @FXML + private void onDuplicateAction(ActionEvent event) { + table.getItems().addAll(table.getSelectionModel().getSelectedItems()); + } + + @FXML + private void onDeleteAction(ActionEvent event) { + table.getItems().removeAll(table.getSelectionModel().getSelectedItems()); + } + + @FXML + private void onTestSelectionAction(ActionEvent event) { + parent.newTest(table.getSelectionModel().getSelectedItems()); + } + + @FXML + private void onTestAction(ActionEvent event) { + parent.newTest(data); + } +} diff --git a/src/main/java/es/kauron/jstudy/controller/TestController.java b/src/main/java/es/kauron/jstudy/controller/TestController.java new file mode 100644 index 0000000..5f72636 --- /dev/null +++ b/src/main/java/es/kauron/jstudy/controller/TestController.java @@ -0,0 +1,68 @@ +package es.kauron.jstudy.controller; + +import com.jfoenix.controls.JFXTextField; +import es.kauron.jstudy.model.TestItem; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; + +import java.net.URL; +import java.util.List; +import java.util.ResourceBundle; + +public class TestController implements Initializable { + @FXML + private Label question, prevQuestion, prevAnswer, correctAnswer, progressLabel, correctLabel; + @FXML + private JFXTextField answer; + @FXML + private ProgressBar progress; + + private List list; + private int total, current; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + } + + void setList(List list) { + this.list = list; + total = list.size(); + progress.setProgress(0); + progressLabel.setText("0/" + total); + onSkipAction(null); + } + + @FXML + private void onNextAction(ActionEvent event) { + prevQuestion.setText(list.get(current).getQuestion()); + prevAnswer.setText(answer.getText()); + correctAnswer.setText(list.get(current).getAnswer()); + + boolean right = list.get(current).getAnswer().equals(answer.getText()); + correctAnswer.setVisible(!right); + correctLabel.setVisible(!right); + + list.remove(current); + progress.setProgress(progress.getProgress() + 1.0/total); + progressLabel.setText((int) (progress.getProgress() * total) + "/" + total); + onSkipAction(event); + } + + @FXML + private void onSkipAction(ActionEvent event) { + if (list.size() == 0) { + answer.setText(""); + answer.setDisable(true); + question.setText("That's it!"); + } else { + answer.setText(""); + current = (int) (Math.random() * list.size()); + question.setText(list.get(current).getQuestion()); + answer.requestFocus(); + } + } +} diff --git a/src/main/java/es/kauron/jstudy/model/TestItem.java b/src/main/java/es/kauron/jstudy/model/TestItem.java new file mode 100644 index 0000000..c57c14a --- /dev/null +++ b/src/main/java/es/kauron/jstudy/model/TestItem.java @@ -0,0 +1,83 @@ +package es.kauron.jstudy.model; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +import java.io.*; +import java.util.ArrayList; +import java.util.InputMismatchException; +import java.util.List; +import java.util.Scanner; + +public class TestItem { + private StringProperty question, answer; + + public TestItem(SimpleStringProperty question, SimpleStringProperty answer) { + this.question = question; + this.answer = answer; + } + + public TestItem(TestItem item) { + this(item.getQuestion(), item.getAnswer()); + } + + public TestItem(String question, String answer) { + this(new SimpleStringProperty(question), new SimpleStringProperty(answer)); + } + + public String getQuestion() { + return question.get(); + } + + public StringProperty questionProperty() { + return question; + } + + public String getAnswer() { + return answer.get(); + } + + public StringProperty answerProperty() { + return answer; + } + + public boolean isValid() { + return !question.get().isEmpty() && !answer.get().isEmpty(); + } + + public boolean checkAnswer(String answer, boolean sensible) { + return sensible ? getAnswer().equals(answer) : getAnswer().equalsIgnoreCase(answer); + } + + public static void saveTo(File file, List data) { + try { + OutputStreamWriter writer = new FileWriter(file); + for (TestItem item : data) { + writer.write(item.getQuestion() + "::" + item.getAnswer() + "\n"); + } + writer.flush(); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static List loadFrom(File file) { + List list = new ArrayList<>(); + try { + Scanner in = new Scanner(file); + while (in.hasNextLine()) { + String line = in.nextLine(); + int index = line.indexOf("::"); + String question = line.substring(0, index); + String answer = line.substring(index + 2); + list.add(new TestItem(question, answer)); + System.err.println(question + " :: " + answer); + } + } catch (FileNotFoundException | InputMismatchException e) { + e.printStackTrace(); + } + return list; + } + +} diff --git a/src/main/main.iml b/src/main/main.iml new file mode 100644 index 0000000..935392e --- /dev/null +++ b/src/main/main.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/es/kauron/jstudy/view/edit.fxml b/src/main/resources/es/kauron/jstudy/view/edit.fxml new file mode 100644 index 0000000..80f7efa --- /dev/null +++ b/src/main/resources/es/kauron/jstudy/view/edit.fxml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + +