Implements database, adds profiles
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
<artifactId>gui-fx</artifactId>
|
||||
|
||||
<properties>
|
||||
<javafx.version>24.0.2</javafx.version>
|
||||
<javafx.version>25</javafx.version>
|
||||
<controlsfx.version>11.2.2</controlsfx.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import ch.gtache.fro.practice.BirdPracticeParameters;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -19,12 +20,27 @@ public final class FXSettingsController implements SettingsController {
|
||||
|
||||
@FXML
|
||||
private TableView<BirdPracticeParameters> table;
|
||||
@FXML
|
||||
private TableColumn<BirdPracticeParameters, Boolean> enabledColumn;
|
||||
@FXML
|
||||
private TableColumn<BirdPracticeParameters, String> birdColumn;
|
||||
@FXML
|
||||
private TableColumn fetchersColumn;
|
||||
@FXML
|
||||
private TableColumn picturesColumn;
|
||||
@FXML
|
||||
private TableColumn soundsColumn;
|
||||
|
||||
@Inject
|
||||
FXSettingsController(final FXSettingsModel model) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void initialize() {
|
||||
table.setItems(model.birdPracticeParameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importSettings() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
@@ -2,6 +2,9 @@ package ch.gtache.fro.gui.fx;
|
||||
|
||||
import ch.gtache.fro.gui.SettingsModel;
|
||||
import ch.gtache.fro.practice.BirdPracticeParameters;
|
||||
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
|
||||
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
|
||||
import ch.gtache.fro.practice.PracticeProfileProvider;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javafx.collections.FXCollections;
|
||||
@@ -16,7 +19,18 @@ public final class FXSettingsModel implements SettingsModel {
|
||||
private final ObservableList<BirdPracticeParameters> birdParameters;
|
||||
|
||||
@Inject
|
||||
FXSettingsModel() {
|
||||
FXSettingsModel(final PracticeProfileProvider profileProvider,
|
||||
final GroupedBirdPracticeParametersManager birdPracticeParametersManager) {
|
||||
this.birdParameters = FXCollections.observableArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableList<BirdPracticeParameters> birdPracticeParameters() {
|
||||
return birdParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupedBirdPracticeParameters configuration() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ch.gtache.fro.practice.gui.fx;
|
||||
|
||||
import ch.gtache.fro.practice.PracticeProfile;
|
||||
import ch.gtache.fro.practice.PracticeRunner;
|
||||
import ch.gtache.fro.practice.QuestionType;
|
||||
import ch.gtache.fro.practice.gui.PracticeSettingsController;
|
||||
@@ -23,6 +24,9 @@ public final class FXPracticeSettingsController implements PracticeSettingsContr
|
||||
private final FXPracticeSettingsModel model;
|
||||
private final QuestionTypeConverter questionTypeConverter;
|
||||
private final PracticeRunner runner;
|
||||
|
||||
@FXML
|
||||
private PrefixSelectionComboBox<PracticeProfile> profileCombobox;
|
||||
@FXML
|
||||
private PrefixSelectionComboBox<QuestionType> questionTypeCombobox;
|
||||
@FXML
|
||||
@@ -51,6 +55,9 @@ public final class FXPracticeSettingsController implements PracticeSettingsContr
|
||||
|
||||
@FXML
|
||||
private void initialize() {
|
||||
profileCombobox.setItems(model.availableProfiles());
|
||||
profileCombobox.valueProperty().bindBidirectional(model.profileProperty());
|
||||
profileCombobox.setConverter(new PracticeProfileConverter());
|
||||
questionTypeCombobox.setItems(model.questionTypes());
|
||||
questionTypeCombobox.valueProperty().bindBidirectional(model.questionTypeProperty());
|
||||
questionTypeCombobox.setConverter(questionTypeConverter);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package ch.gtache.fro.practice.gui.fx;
|
||||
|
||||
import ch.gtache.fro.practice.PracticeConfiguration;
|
||||
import ch.gtache.fro.practice.GroupedBirdPracticeParameters;
|
||||
import ch.gtache.fro.practice.GroupedBirdPracticeParametersManager;
|
||||
import ch.gtache.fro.practice.PracticeParameters;
|
||||
import ch.gtache.fro.practice.PracticeProfile;
|
||||
import ch.gtache.fro.practice.PracticeProfileProvider;
|
||||
import ch.gtache.fro.practice.PracticeRun;
|
||||
import ch.gtache.fro.practice.QuestionType;
|
||||
import ch.gtache.fro.practice.gui.PracticeSettingsModel;
|
||||
@@ -28,9 +31,13 @@ import java.util.Map;
|
||||
@Singleton
|
||||
public final class FXPracticeSettingsModel implements PracticeSettingsModel {
|
||||
|
||||
private static final int DEFAULT_GUESSES_NUMBER = 1;
|
||||
private static final int DEFAULT_QUESTIONS_NUMBER = 20;
|
||||
private static final int DEFAULT_SUGGESTIONS_NUMBER = 4;
|
||||
|
||||
private final ObservableList<PracticeProfile> availableProfiles;
|
||||
private final ObjectProperty<PracticeProfile> profile;
|
||||
private final ReadOnlyObjectWrapper<GroupedBirdPracticeParameters> birdPracticeParameters;
|
||||
private final ObservableList<QuestionType> questionTypes;
|
||||
private final ObjectProperty<QuestionType> questionType;
|
||||
private final ReadOnlyBooleanWrapper hasSuggestions;
|
||||
@@ -41,19 +48,51 @@ public final class FXPracticeSettingsModel implements PracticeSettingsModel {
|
||||
private final ObjectProperty<PracticeRun> practiceRun;
|
||||
|
||||
@Inject
|
||||
FXPracticeSettingsModel(final PracticeConfiguration configuration) {
|
||||
FXPracticeSettingsModel(final PracticeProfileProvider profileProvider,
|
||||
final GroupedBirdPracticeParametersManager birdParametersManager) {
|
||||
this.availableProfiles = FXCollections.observableArrayList(profileProvider.getAllObjectsAsync().join());
|
||||
this.profile = new SimpleObjectProperty<>(availableProfiles.getFirst());
|
||||
this.birdPracticeParameters = new ReadOnlyObjectWrapper<>(birdParametersManager.getObjectAsync(profile()).join());
|
||||
this.questionTypes = FXCollections.observableArrayList(QuestionType.values());
|
||||
this.questionType = new SimpleObjectProperty<>(QuestionType.PICTURE_EXACT);
|
||||
this.hasSuggestions = new ReadOnlyBooleanWrapper(true);
|
||||
this.guessesNumber = new SimpleIntegerProperty(configuration.guessesNumber());
|
||||
this.guessesNumber = new SimpleIntegerProperty(DEFAULT_GUESSES_NUMBER);
|
||||
this.questionsNumber = new SimpleIntegerProperty(DEFAULT_QUESTIONS_NUMBER);
|
||||
this.suggestionsNumber = new SimpleIntegerProperty(DEFAULT_SUGGESTIONS_NUMBER);
|
||||
this.practiceParameters = new ReadOnlyObjectWrapper<>();
|
||||
this.practiceRun = new SimpleObjectProperty<>();
|
||||
practiceParameters.bind(Bindings.createObjectBinding(() -> new PracticeParametersImpl(configuration.birdPracticeParameters(), Map.of(questionType(), 1.0),
|
||||
guessesNumber(), questionsNumber(), suggestionsNumber()), questionType, guessesNumber, questionsNumber, suggestionsNumber));
|
||||
birdPracticeParameters.bind(Bindings.createObjectBinding(() -> birdParametersManager.getObjectAsync(profile()).join(), profile));
|
||||
practiceParameters.bind(Bindings.createObjectBinding(() -> new PracticeParametersImpl(birdPracticeParameters(), Map.of(questionType(), 1.0),
|
||||
guessesNumber(), questionsNumber(), suggestionsNumber()), birdPracticeParameters, questionType, guessesNumber, questionsNumber, suggestionsNumber));
|
||||
hasSuggestions.bind(questionType.isNotEqualTo(QuestionType.PICTURE_EXACT).and(questionType.isNotEqualTo(QuestionType.SOUND_EXACT)));
|
||||
guessesNumber.addListener((_, _, newValue) -> configuration.setGuessesNumber(newValue.intValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableList<PracticeProfile> availableProfiles() {
|
||||
return availableProfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PracticeProfile profile() {
|
||||
return profile.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProfile(final PracticeProfile profile) {
|
||||
this.profile.set(profile);
|
||||
}
|
||||
|
||||
ObjectProperty<PracticeProfile> profileProperty() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupedBirdPracticeParameters birdPracticeParameters() {
|
||||
return birdPracticeParameters.get();
|
||||
}
|
||||
|
||||
ReadOnlyObjectProperty<GroupedBirdPracticeParameters> birdPracticeParametersProperty() {
|
||||
return birdPracticeParameters.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package ch.gtache.fro.practice.gui.fx;
|
||||
|
||||
import ch.gtache.fro.practice.PracticeProfile;
|
||||
import jakarta.inject.Inject;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* {@link StringConverter} for {@link PracticeProfile}
|
||||
*/
|
||||
public class PracticeProfileConverter extends StringConverter<PracticeProfile> {
|
||||
|
||||
@Inject
|
||||
PracticeProfileConverter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(final PracticeProfile object) {
|
||||
return object.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PracticeProfile fromString(final String string) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,9 @@ import javafx.util.StringConverter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* {@link StringConverter} for {@link QuestionType}
|
||||
*/
|
||||
public class QuestionTypeConverter extends StringConverter<QuestionType> {
|
||||
|
||||
private final QuestionTypeTranslator translator;
|
||||
|
||||
@@ -5,7 +5,7 @@ import ch.gtache.fro.BirdProvider;
|
||||
import ch.gtache.fro.BirdTranslator;
|
||||
import ch.gtache.fro.ProvisionException;
|
||||
import ch.gtache.fro.TranslationException;
|
||||
import ch.gtache.fro.impl.BirdImpl;
|
||||
import ch.gtache.fro.impl.MinimalBirdImpl;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class UserInputNormalizer {
|
||||
|
||||
Bird getBird(final String input) {
|
||||
final var normalized = normalize(input);
|
||||
return birdMap.getOrDefault(normalized, new BirdImpl(input));
|
||||
return birdMap.getOrDefault(normalized, new MinimalBirdImpl(input));
|
||||
}
|
||||
|
||||
private static String normalize(final CharSequence input) {
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
|
||||
<columns>
|
||||
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
|
||||
text="%settings.table.column.enabled"/>
|
||||
text="%settings.table.column.bird" fx:id="birdColumn"/>
|
||||
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
|
||||
text="%settings.table.column.bird"/>
|
||||
text="%settings.table.column.enabled" fx:id="enabledColumn"/>
|
||||
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
|
||||
text="%settings.table.column.fetchers"/>
|
||||
text="%settings.table.column.fetchers" fx:id="fetchersColumn"/>
|
||||
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
|
||||
text="%settings.table.column.pictures"/>
|
||||
text="%settings.table.column.pictures" fx:id="picturesColumn"/>
|
||||
<TableColumn maxWidth="1.7976931348623157E308" minWidth="-1.0" prefWidth="75.0"
|
||||
text="%settings.table.column.sounds"/>
|
||||
text="%settings.table.column.sounds" fx:id="soundsColumn"/>
|
||||
</columns>
|
||||
<columnResizePolicy>
|
||||
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
|
||||
|
||||
@@ -4,36 +4,38 @@
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.controlsfx.control.PrefixSelectionComboBox?>
|
||||
<?import org.controlsfx.control.textfield.CustomTextField?>
|
||||
|
||||
<GridPane hgap="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" vgap="10.0" xmlns="http://javafx.com/javafx/24.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticePictureExactController">
|
||||
<GridPane hgap="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" vgap="10.0"
|
||||
xmlns="http://javafx.com/javafx/24.0.1" xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticePictureExactController">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="ALWAYS" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
<ColumnConstraints hgrow="ALWAYS"/>
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="ALWAYS" />
|
||||
<RowConstraints vgrow="ALWAYS" />
|
||||
<RowConstraints vgrow="ALWAYS" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="ALWAYS"/>
|
||||
<RowConstraints vgrow="ALWAYS"/>
|
||||
<RowConstraints vgrow="ALWAYS"/>
|
||||
<RowConstraints vgrow="SOMETIMES"/>
|
||||
<RowConstraints vgrow="SOMETIMES"/>
|
||||
<RowConstraints vgrow="SOMETIMES"/>
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<ImageView fx:id="pictureView" fitHeight="800.0" fitWidth="800.0" pickOnBounds="true" preserveRatio="true" GridPane.columnSpan="2147483647" GridPane.rowIndex="1" />
|
||||
<CustomTextField fx:id="inputField" onAction="#enterPressed" GridPane.rowIndex="3" />
|
||||
<PrefixSelectionComboBox fx:id="typeCombobox" managed="false" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed" text="%practice.picture.exact.validate.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="5" />
|
||||
<Label fx:id="progressLabel" text="Label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" />
|
||||
<VBox fx:id="guessesBox" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
||||
<Label fx:id="answerLabel" GridPane.rowIndex="2" />
|
||||
<ImageView fx:id="pictureView" fitHeight="800.0" fitWidth="800.0" pickOnBounds="true" preserveRatio="true"
|
||||
GridPane.columnSpan="2147483647" GridPane.rowIndex="1"/>
|
||||
<CustomTextField fx:id="inputField" onAction="#enterPressed" GridPane.rowIndex="3"/>
|
||||
<PrefixSelectionComboBox fx:id="typeCombobox" managed="false" visible="false" GridPane.columnIndex="1"
|
||||
GridPane.rowIndex="3"/>
|
||||
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed"
|
||||
text="%practice.picture.exact.validate.button.label" GridPane.columnSpan="2147483647"
|
||||
GridPane.halignment="CENTER" GridPane.rowIndex="5"/>
|
||||
<Label fx:id="progressLabel" text="Label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"/>
|
||||
<VBox fx:id="guessesBox" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4"/>
|
||||
<Label fx:id="answerLabel" GridPane.rowIndex="2" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"/>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
|
||||
</padding>
|
||||
</GridPane>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<ColumnConstraints hgrow="SOMETIMES" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
@@ -22,15 +23,17 @@
|
||||
<RowConstraints vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="%practice.settings.type.label" />
|
||||
<PrefixSelectionComboBox fx:id="questionTypeCombobox" GridPane.columnIndex="1" />
|
||||
<Label fx:id="suggestionsNumberLabel" text="%practice.settings.suggestions.number.label" GridPane.rowIndex="3" />
|
||||
<Spinner fx:id="suggestionsNumberSpinner" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Button mnemonicParsing="false" onAction="#startPressed" text="%practice.settings.start.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
||||
<Label text="%practice.settings.questions.number.label" GridPane.rowIndex="1" />
|
||||
<Spinner fx:id="questionsNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<Label text="%practice.settings.guesses.number.label" GridPane.rowIndex="2" />
|
||||
<Spinner fx:id="guessesNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||
<Label text="%practice.settings.type.label" GridPane.rowIndex="1" />
|
||||
<PrefixSelectionComboBox fx:id="questionTypeCombobox" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<Label fx:id="suggestionsNumberLabel" text="%practice.settings.suggestions.number.label" GridPane.rowIndex="4" />
|
||||
<Spinner fx:id="suggestionsNumberSpinner" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
||||
<Button mnemonicParsing="false" onAction="#startPressed" text="%practice.settings.start.button.label" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER" GridPane.rowIndex="5" />
|
||||
<Label text="%practice.settings.questions.number.label" GridPane.rowIndex="2" />
|
||||
<Spinner fx:id="questionsNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||
<Label text="%practice.settings.guesses.number.label" GridPane.rowIndex="3" />
|
||||
<Spinner fx:id="guessesNumberSpinner" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||
<Label text="%practice.settings.profile.label" />
|
||||
<PrefixSelectionComboBox fx:id="profileCombobox" GridPane.columnIndex="1" />
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
|
||||
Reference in New Issue
Block a user