mirror of
https://gitlab.com/kauron/jstudy
synced 2024-12-22 08:23:33 +01:00
Table: new editing and filtering
* Split buttons between the context menu and above the table. * Moved adding/editing to above the table. * Added filtering. * Added shortcut to edit (double click) and to delete rows.
This commit is contained in:
parent
93b7dce200
commit
7fe80b07ec
2 changed files with 76 additions and 57 deletions
|
@ -1,50 +1,47 @@
|
|||
package es.kauron.jstudy.controller;
|
||||
|
||||
import es.kauron.jstudy.Main;
|
||||
import es.kauron.jstudy.model.AppPrefs;
|
||||
import es.kauron.jstudy.model.TestItem;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
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.SelectionMode;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.*;
|
||||
|
||||
public class TableController implements Initializable {
|
||||
@FXML
|
||||
private TableView<TestItem> table;
|
||||
@FXML
|
||||
private TextField newQuestionField, newAnswerField, searchField;
|
||||
@FXML
|
||||
private Button addButton;
|
||||
@FXML
|
||||
private TableColumn<TestItem, String> answerCol, questionCol;
|
||||
|
||||
private FilteredList<TestItem> filtered;
|
||||
private ObservableList<TestItem> data;
|
||||
private Controller parent;
|
||||
private File file;
|
||||
StringProperty name;
|
||||
final BooleanProperty saved = new SimpleBooleanProperty();
|
||||
private final ObjectProperty<TestItem> editing = new SimpleObjectProperty<>(null);
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
addButton.textProperty().bind(Bindings.when(editing.isNull()).then("_Add item").otherwise("_Save item"));
|
||||
// Add context menu to Table
|
||||
MenuItem menuEdit = new MenuItem("_Edit");
|
||||
menuEdit.setOnAction(this::onEditAction);
|
||||
|
@ -61,16 +58,18 @@ public class TableController implements Initializable {
|
|||
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||
answerCol.setCellValueFactory(e -> e.getValue().answerProperty());
|
||||
questionCol.setCellValueFactory(e -> e.getValue().questionProperty());
|
||||
table.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<? super Integer>) obs -> {
|
||||
menuEdit.setDisable(obs.getList().size() != 1);
|
||||
});
|
||||
table.getSelectionModel().getSelectedIndices().addListener(
|
||||
(ListChangeListener<? super Integer>) obs -> menuEdit.setDisable(obs.getList().size() != 1));
|
||||
searchField.textProperty().addListener((obj, o, n) ->
|
||||
filtered.setPredicate((item) -> item.getQuestion().contains(n) || item.getAnswer().contains(n)));
|
||||
}
|
||||
|
||||
void setData(String name, List<TestItem> list, Controller controller, File file) {
|
||||
this.name = new SimpleStringProperty(name);
|
||||
this.data = FXCollections.observableArrayList(list);
|
||||
this.filtered = data.filtered((item) -> true);
|
||||
this.parent = controller;
|
||||
table.setItems(data);
|
||||
table.setItems(filtered);
|
||||
this.file = file;
|
||||
saved.set(file != null);
|
||||
}
|
||||
|
@ -99,41 +98,31 @@ public class TableController implements Initializable {
|
|||
|
||||
@FXML
|
||||
protected void onAddAction(ActionEvent event) {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/edit.fxml"));
|
||||
Parent pRoot = loader.load();
|
||||
|
||||
((EditController) loader.getController()).setList(data, saved);
|
||||
|
||||
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();
|
||||
if (editing.get() == null) {
|
||||
TestItem item = new TestItem(newQuestionField.getText().trim(), newAnswerField.getText().trim());
|
||||
data.add(item);
|
||||
newQuestionField.setText("");
|
||||
newAnswerField.setText("");
|
||||
saved.set(false);
|
||||
} else {
|
||||
editing.get().answerProperty().set(newAnswerField.getText().trim());
|
||||
editing.get().questionProperty().set(newQuestionField.getText().trim());
|
||||
editing.set(null);
|
||||
newQuestionField.setText("");
|
||||
newAnswerField.setText("");
|
||||
}
|
||||
newQuestionField.requestFocus();
|
||||
}
|
||||
|
||||
@FXML
|
||||
protected void onEditAction(ActionEvent event) {
|
||||
ObservableList<Integer> list = table.getSelectionModel().getSelectedIndices();
|
||||
ObservableList<TestItem> list = table.getSelectionModel().getSelectedItems();
|
||||
if (list.size() != 1) return;
|
||||
int index = list.get(0);
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/edit.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
((EditController) loader.getController()).setList(table.getItems(), index, saved);
|
||||
|
||||
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();
|
||||
}
|
||||
editing.set(list.get(0));
|
||||
newQuestionField.setText(list.get(0).getQuestion());
|
||||
newAnswerField.setText(list.get(0).getAnswer());
|
||||
saved.set(false);
|
||||
newQuestionField.requestFocus();
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
@ -151,15 +140,14 @@ public class TableController implements Initializable {
|
|||
protected void onDuplicateAction(ActionEvent event) {
|
||||
if (table.getSelectionModel().getSelectedIndices().size() > 0) saved.set(false);
|
||||
for (int i : table.getSelectionModel().getSelectedIndices())
|
||||
table.getItems().add(new TestItem(table.getItems().get(i)));
|
||||
data.add(new TestItem(filtered.get(i)));
|
||||
table.requestFocus();
|
||||
}
|
||||
|
||||
@FXML
|
||||
protected void onDeleteAction(ActionEvent event) {
|
||||
if (table.getSelectionModel().getSelectedIndices().size() > 0) saved.set(false);
|
||||
for (int i : table.getSelectionModel().getSelectedIndices())
|
||||
table.getItems().remove(i);
|
||||
data.removeAll(table.getSelectionModel().getSelectedItems());
|
||||
table.requestFocus();
|
||||
}
|
||||
|
||||
|
@ -170,6 +158,32 @@ public class TableController implements Initializable {
|
|||
|
||||
@FXML
|
||||
protected void onTestAction(ActionEvent event) {
|
||||
parent.newTest(data);
|
||||
parent.newTest(filtered);
|
||||
}
|
||||
|
||||
@FXML
|
||||
protected void onTableKeyEvent(KeyEvent event) {
|
||||
if (event.getCode().equals(KeyCode.DELETE)) {
|
||||
onDeleteAction(null);
|
||||
}
|
||||
}
|
||||
|
||||
private final Timer timer = new Timer();
|
||||
private TimerTask timerTask = null;
|
||||
@FXML
|
||||
protected void onTableMouseClicked(MouseEvent event) {
|
||||
if (timerTask == null) {
|
||||
timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
timerTask = null;
|
||||
}
|
||||
};
|
||||
timer.schedule(timerTask, 200);
|
||||
} else {
|
||||
if (timerTask.cancel())
|
||||
onEditAction(null);
|
||||
timerTask = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,14 @@
|
|||
<children>
|
||||
<HBox alignment="CENTER_LEFT" spacing="5.0">
|
||||
<children>
|
||||
<Button defaultButton="true" onAction="#onAddAction" prefWidth="105.0" text="_Add new">
|
||||
<TextField fx:id="newQuestionField" promptText="Question" />
|
||||
<TextField fx:id="newAnswerField" promptText="Answer" />
|
||||
<Button defaultButton="true" fx:id="addButton" onAction="#onAddAction" prefWidth="105.0" text="_Add new">
|
||||
<tooltip>
|
||||
<Tooltip text="Add a new entry to the table" />
|
||||
</tooltip>
|
||||
</Button>
|
||||
<TextField fx:id="searchField" promptText="Search..." />
|
||||
<HBox alignment="CENTER_RIGHT" spacing="5.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS">
|
||||
<children>
|
||||
<Button layoutX="10.0" layoutY="273.0" onAction="#onTestAction" prefWidth="105.0" text="_Test all">
|
||||
|
@ -35,7 +38,9 @@
|
|||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</VBox.margin>
|
||||
</HBox>
|
||||
<TableView fx:id="table" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS">
|
||||
<TableView fx:id="table" onMouseClicked="#onTableMouseClicked" onKeyPressed="#onTableKeyEvent" maxHeight="1.7976931348623157E308"
|
||||
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity"
|
||||
prefHeight="200.0" prefWidth="400.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn fx:id="questionCol" prefWidth="75.0" text="Question" />
|
||||
<TableColumn fx:id="answerCol" prefWidth="75.0" text="Answer" />
|
||||
|
|
Loading…
Reference in a new issue