From e3c2e1f01a95c5191bb978840b87a7835135bddc Mon Sep 17 00:00:00 2001 From: AliScrooge <45091862+AliScrooge@users.noreply.github.com> Date: Sat, 26 Feb 2022 17:15:12 +0100 Subject: [PATCH 1/9] Correction du gradle.yml --- .github/workflows/gradle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 24fcff91..3d695165 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,6 +13,7 @@ on: jobs: create_release: + permissions: write-all name: Create release runs-on: ubuntu-latest steps: From 2a40556fecb77a0008073071385d597151244f27 Mon Sep 17 00:00:00 2001 From: Valentin MIGNOT Date: Fri, 13 Jan 2023 15:39:18 +0100 Subject: [PATCH 2/9] load my correction on the git --- .github/workflows/gradle.yml | 3 +- README.md | 2 +- build.gradle | 6 +- gradle/wrapper/gradle-wrapper.properties | 4 +- src/main/java/application/UPMTApp.java | 10 +- .../ApplicationCommandFactory.java | 1 + .../appCommands/ChangeLanguageCommand.java | 1 + .../appCommands/CloseApplicationCommand.java | 27 ++- .../SetAutoScrollWhenRevealCommand.java | 1 + .../configuration/Configuration.java | 1 + .../project/controllers/ProjectDialogBox.java | 3 + .../Controllers/RichTextAreaController.java | 3 +- .../tools/Controllers/ToolController.java | 2 +- .../InterviewSelectorCellController.java | 1 + .../controller/MainViewController.java | 9 +- .../AddConcreteCategoryCommand.java | 14 +- .../ConcreteCategoryCommandFactory.java | 2 +- .../RemoveConcreteCategoryCommand.java | 10 +- .../modelCommands/RemoveConcreteCategory.java | 4 +- .../appCommands/AddSiblingMomentCommand.java | 32 ++- .../appCommands/ChangeColorMomentCommand.java | 4 - .../appCommands/DeleteMomentCommand.java | 10 +- .../appCommands/MergeMomentCommand.java | 149 +++++++++++++ .../appCommands/MomentCommandFactory.java | 16 +- .../moment/appCommands/MoveMomentCommand.java | 21 ++ .../moment/controllers/MomentController.java | 71 +++--- .../MomentSeparatorController.java | 16 +- .../moment/modelCommands/MoveMoment.java | 7 +- .../moment/modelCommands/SetMomentTrans.java | 2 + .../EditConcretePropertyCommand.java | 37 ++++ .../ConcretePropertyController.java | 102 ++++++--- .../Controllers/RootLayoutController.java | 6 +- .../Controllers/SchemaTreeCellController.java | 15 +- .../SchemaTreeFolderController.java | 6 + .../SchemaTreeMomentTypeController.java | 119 ++++++++++ .../Controllers/SchemaTreeRootController.java | 11 +- .../schemaTree/Cell/SchemaTreeCell.java | 116 +++++----- .../components/schemaTree/Cell/Utils.java | 5 + .../CanTreeElementBeSafelyDeletedVisitor.java | 11 +- .../CanTreeElementBeSafelyRenamedVisitor.java | 11 +- .../CreateAddChildStrategyVisitor.java | 11 +- .../Visitors/CreateControllerVisitor.java | 11 +- .../CreateRemovingStrategyVisitor.java | 11 +- .../Visitors/CreateSchemaTreeItemVisitor.java | 15 +- .../Visitors/SchemaTreePluggableVisitor.java | 7 +- .../ChangeColorCategoryCommand.java | 8 - .../appCommands/SchemaTreeCommandFactory.java | 8 + .../RenameSchemaMomentTypes.java | 28 +++ .../Controllers/SchemaTreeController.java | 8 +- .../ResetCategoryUsesCounterVisitor.java | 13 +- .../ResetPropertyUsesCounterVisitor.java | 13 +- .../AddSchemaMomentTypeCommand.java | 23 ++ .../RemoveSchemaMomentTypeCommand.java | 23 ++ .../appCommand/RenameMomentTypesCommand.java | 25 +++ .../controllers/MomentTypeController.java | 138 ++++++++++++ .../controllers/ToolBoxControllers.java | 182 ++++++++++++++++ .../history/commands/AddSchemaMomentType.java | 27 +++ .../RemoveCategoryFromMomentType.java | 28 +++ .../commands/RemoveSchemaMomentType.java | 27 +++ src/main/java/models/ConcreteCategory.java | 2 +- src/main/java/models/ConcreteProperty.java | 3 +- src/main/java/models/Moment.java | 69 ++++-- src/main/java/models/Project.java | 14 ++ src/main/java/models/RootMoment.java | 8 + src/main/java/models/SchemaCategory.java | 1 - src/main/java/models/SchemaElement.java | 6 +- src/main/java/models/SchemaFolder.java | 60 ++++-- src/main/java/models/SchemaMomentType.java | 203 ++++++++++++++++++ src/main/java/models/SchemaTreeRoot.java | 137 ++++++++---- .../persistency/Export/ProjectExporter.java | 1 + src/main/java/persistency/ProjectLoader.java | 1 - .../newSaveSystem/SMomentTypeController.java | 53 +++++ .../persistency/newSaveSystem/SProject.java | 23 +- .../newSaveSystem/SSchemaCategory.java | 2 +- .../newSaveSystem/SSchemaFolder.java | 43 +++- .../newSaveSystem/SSchemaMomentType.java | 84 ++++++++ .../newSaveSystem/SSchemaTreeRoot.java | 49 ++++- .../serialization/ObjectSerializer.java | 3 + .../serialization/Serializable.java | 7 +- .../serialization/json/JSONSerializer.java | 6 + .../SuggestionStrategyCategory.java | 5 + .../SuggestionStrategyProperty.java | 6 + src/main/java/utils/popups/MergerPopup.java | 80 +++++++ src/main/resources/bundles/Lang_en.properties | 104 +++------ src/main/resources/bundles/Lang_fr.properties | 108 +++------- src/main/resources/css/application.css | 10 +- src/main/resources/css/toolbox.css | 32 +++ src/main/resources/images/toolBox_icon.png | Bin 0 -> 11386 bytes src/main/resources/views/AboutUs/AboutUs.fxml | 6 +- .../views/InterviewPanel/InterviewPanel.fxml | 6 +- .../views/InterviewPanel/InterviewText.fxml | 2 +- .../InterviewPanel/InterviewTextArea.fxml | 2 +- .../InterviewSelector/InterviewSelector.fxml | 4 +- .../InterviewSelectorCell.fxml | 4 +- .../resources/views/MainView/MainView.fxml | 27 ++- .../views/Project/ModifyInterviewView.fxml | 6 +- .../views/Project/NewInterviewView.fxml | 8 +- .../views/Project/NewProjectView.fxml | 6 +- .../views/Project/ProjectSelectionView.fxml | 8 +- .../views/RootLayout/RootLayout.fxml | 2 +- .../views/SchemaTree/SchemaTree.fxml | 2 +- .../views/SchemaTree/SchemaTreeCell.fxml | 11 +- .../views/TemplateSpace/TemplateMoment.fxml | 4 +- .../views/TemplateSpace/TemplateSpace.fxml | 2 +- src/main/resources/views/Toolbox/Toolbox.fxml | 23 ++ .../views/Toolbox/components/MomentType.fxml | 10 + .../Justification/Justification.fxml | 2 +- .../EditJustificationCell.fxml | 2 +- .../JustificationCell/JustificationCell.fxml | 6 +- .../Justification/Shift.fxml | 6 +- .../modelisationSpace/ModelisationSpace.fxml | 2 +- .../concreteCategory/ConcreteCategory.fxml | 6 +- .../concreteProperty/ConcreteProperty.fxml | 5 +- .../modelisationSpace/moment/Moment.fxml | 8 +- .../modelisationSpace/moment/RootMoment.fxml | 2 +- .../views/utils/popups/MergingPopup.fxml | 22 ++ .../views/utils/popups/TextEntry.fxml | 2 +- .../resources/views/utils/popups/Warning.fxml | 4 +- 118 files changed, 2221 insertions(+), 576 deletions(-) create mode 100644 src/main/java/components/modelisationSpace/moment/appCommands/MergeMomentCommand.java create mode 100644 src/main/java/components/modelisationSpace/property/appCommands/EditConcretePropertyCommand.java create mode 100644 src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeMomentTypeController.java create mode 100644 src/main/java/components/schemaTree/Cell/modelCommands/RenameSchemaMomentTypes.java create mode 100644 src/main/java/components/toolbox/appCommand/AddSchemaMomentTypeCommand.java create mode 100644 src/main/java/components/toolbox/appCommand/RemoveSchemaMomentTypeCommand.java create mode 100644 src/main/java/components/toolbox/appCommand/RenameMomentTypesCommand.java create mode 100644 src/main/java/components/toolbox/controllers/MomentTypeController.java create mode 100644 src/main/java/components/toolbox/controllers/ToolBoxControllers.java create mode 100644 src/main/java/components/toolbox/history/commands/AddSchemaMomentType.java create mode 100644 src/main/java/components/toolbox/history/commands/RemoveCategoryFromMomentType.java create mode 100644 src/main/java/components/toolbox/history/commands/RemoveSchemaMomentType.java create mode 100644 src/main/java/models/SchemaMomentType.java create mode 100644 src/main/java/persistency/newSaveSystem/SMomentTypeController.java create mode 100644 src/main/java/persistency/newSaveSystem/SSchemaMomentType.java create mode 100644 src/main/java/utils/popups/MergerPopup.java create mode 100644 src/main/resources/css/toolbox.css create mode 100644 src/main/resources/images/toolBox_icon.png create mode 100644 src/main/resources/views/Toolbox/Toolbox.fxml create mode 100644 src/main/resources/views/Toolbox/components/MomentType.fxml create mode 100644 src/main/resources/views/utils/popups/MergingPopup.fxml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 3d695165..986382f5 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,7 +13,6 @@ on: jobs: create_release: - permissions: write-all name: Create release runs-on: ubuntu-latest steps: @@ -42,7 +41,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] - java: [11] + java: [15] steps: - uses: actions/checkout@v2 - name: Set up JDK diff --git a/README.md b/README.md index 228cfe67..d7ab5275 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ uPMT is aimed at researchers using microphenomenology interviews (also know as explicitation interviews) to study lived experience. It has been designed to help analyze the micro-dynamics of experience as described in interview transcriptions, by modelling and formalizing the sequential unfolding of "experience moments" described with categories and properties, and linked to the descriptemes - excerpts of the transcript - that justify them. -Current work is carried out by Yves Motteux and Esteban Jamin. Past developers were Gabriel Jolly (20-21), Xavier Tremillon, Yahuan Chen and Nathan Seva (19-20), Gwenaelle Gouriten, Salma Hichami and Othman Houmair (18-19), and Mehdi Haddad, Eva Boon and Yinxing Huang (17-18), under the supervision of Yannick Prié. The first version of the software was implemented by Corentin Jezequel in late 2017, under the supervision of Yannick Prié and Thomas Rabeyron. +Current work is carried out by Gabriel Jolly, Thomas Clouet and Célian Rolland. Past developers were Yves Motteux and Esteban Jamin (20-21), Xavier Tremillon, Yahuan Chen and Nathan Seva (19-20), Gwenaelle Gouriten, Salma Hichami and Othman Houmair (18-19), and Mehdi Haddad, Eva Boon and Yinxing Huang (17-18), under the supervision of Yannick Prié. The first version of the software was implemented by Corentin Jezequel in late 2017, under the supervision of Yannick Prié and Thomas Rabeyron. Download the latest version at: https://github.com/yprie/uPMT/releases diff --git a/build.gradle b/build.gradle index 7f267414..f966dbf7 100644 --- a/build.gradle +++ b/build.gradle @@ -21,8 +21,8 @@ repositories { dependencies { implementation 'com.google.code.gson:gson:2.8.2' - compile group: 'org.json', name: 'json', version: '20190722' - compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.10.4' + implementation group: 'org.json', name: 'json', version: '20190722' + implementation group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.10.4' // Use JUnit test framework testImplementation 'junit:junit:4.12' @@ -48,6 +48,8 @@ tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } + + test { systemProperty "file.encoding", "utf-8" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 94920145..ae923763 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/src/main/java/application/UPMTApp.java b/src/main/java/application/UPMTApp.java index ec251721..694e3149 100644 --- a/src/main/java/application/UPMTApp.java +++ b/src/main/java/application/UPMTApp.java @@ -3,7 +3,9 @@ import application.appCommands.ApplicationCommandFactory; import application.configuration.Configuration; import application.history.HistoryManager; +import com.sun.javafx.css.StyleManager; import components.rootLayout.Controllers.RootLayoutController; +import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; @@ -33,11 +35,15 @@ public UPMTApp(Stage primaryStage) throws IOException { HistoryManager.init(appCommandFactory); Scene mainScene = new Scene(RootLayoutController.createRootLayout(rootLayoutController)); + + //set default stylesheet + Application.setUserAgentStylesheet(null); + StyleManager.getInstance().addUserAgentStylesheet(this.getClass().getResource("/css/application.css").toExternalForm()); + primaryStage.setScene(mainScene); - primaryStage.setOnCloseRequest(event -> { appCommandFactory.closeApplication(event).execute(); }); + primaryStage.setOnCloseRequest(event -> appCommandFactory.closeApplication(event).execute()); primaryStage.show(); - //Load the last used project or ask for a new one. if(Configuration.getProjectsPath().length > 0){ appCommandFactory.openRecentProject(Configuration.getProjectsPath()[0]).execute(); diff --git a/src/main/java/application/appCommands/ApplicationCommandFactory.java b/src/main/java/application/appCommands/ApplicationCommandFactory.java index 9a8468c4..4b616ecc 100644 --- a/src/main/java/application/appCommands/ApplicationCommandFactory.java +++ b/src/main/java/application/appCommands/ApplicationCommandFactory.java @@ -16,6 +16,7 @@ public ApplicationCommandFactory(UPMTApp app) { this.application = app; } + public CloseApplicationCommand closeApplication() { return new CloseApplicationCommand(this, application); } public CloseApplicationCommand closeApplication(WindowEvent event) { return new CloseApplicationCommand(this, application, event); } public ChangeApplicationTitleCommand changeApplicationTitle(String newTitle) { return new ChangeApplicationTitleCommand(application, newTitle); } public OpenProjectManagerCommand openProjectManagerCommand() { return new OpenProjectManagerCommand(application); } diff --git a/src/main/java/application/appCommands/ChangeLanguageCommand.java b/src/main/java/application/appCommands/ChangeLanguageCommand.java index 41d4b22c..fb173b8b 100644 --- a/src/main/java/application/appCommands/ChangeLanguageCommand.java +++ b/src/main/java/application/appCommands/ChangeLanguageCommand.java @@ -25,6 +25,7 @@ public Void execute() { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(Configuration.langBundle.getString("error")); alert.setHeaderText(Configuration.langBundle.getString("application_language_change_failed")); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); } return null; diff --git a/src/main/java/application/appCommands/CloseApplicationCommand.java b/src/main/java/application/appCommands/CloseApplicationCommand.java index 0ab6ddb1..2bd9dd85 100644 --- a/src/main/java/application/appCommands/CloseApplicationCommand.java +++ b/src/main/java/application/appCommands/CloseApplicationCommand.java @@ -14,21 +14,25 @@ public class CloseApplicationCommand extends ApplicationCommand { - public CloseApplicationCommand(ApplicationCommandFactory appCommandFactory, UPMTApp application, WindowEvent event) { + public CloseApplicationCommand(ApplicationCommandFactory appCommandFactory, UPMTApp application) { super(application); - this.event = event; this.appCommandFactory = appCommandFactory; + this.event = null; + } + + public CloseApplicationCommand(ApplicationCommandFactory appCommandFactory, UPMTApp application, WindowEvent event) { + super(application); + this.appCommandFactory = appCommandFactory; + this.event = event; } - WindowEvent event; ApplicationCommandFactory appCommandFactory; + WindowEvent event; @Override public Void execute() { - System.out.println("Test checking project unsaved"); - //TODO check for unsaved work boolean workUnsaved = false; String currentTitle = upmtApp.getPrimaryStage().getTitle(); UUID currentCommandId = HistoryManager.getCurrentCommandId(); @@ -49,6 +53,7 @@ public Void execute() { alert.setHeaderText(""); alert.setTitle(Configuration.langBundle.getString("alert_unsaved_project_title")); alert.setContentText(Configuration.langBundle.getString("alert_unsaved_project")); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); ButtonType buttonTypeOne = new ButtonType(Configuration.langBundle.getString("alert_unsaved_project_buttonTypeOne")); ButtonType buttonTypeTwo = new ButtonType(Configuration.langBundle.getString("alert_unsaved_project_buttonTypeTwo")); @@ -64,11 +69,17 @@ public Void execute() { } else if (result.get() == buttonTypeTwo) { // ... user chose "Quit without saving" System.exit(0); - } else { - // ... user chose CANCEL or closed the dialog - event.consume(); + } else if (result.get() == buttonTypeCancel) { + // ... user chose "Cancel" + if (event != null) { + event.consume(); + } + return null; } + } else { + System.exit(0); } + return null; } } diff --git a/src/main/java/application/appCommands/SetAutoScrollWhenRevealCommand.java b/src/main/java/application/appCommands/SetAutoScrollWhenRevealCommand.java index 7a3fcff4..f589a3d2 100644 --- a/src/main/java/application/appCommands/SetAutoScrollWhenRevealCommand.java +++ b/src/main/java/application/appCommands/SetAutoScrollWhenRevealCommand.java @@ -25,6 +25,7 @@ public Void execute() { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(Configuration.langBundle.getString("error")); alert.setHeaderText(Configuration.langBundle.getString("application_settings_failed")); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); } return null; diff --git a/src/main/java/application/configuration/Configuration.java b/src/main/java/application/configuration/Configuration.java index dc964b6e..db5d8b1a 100644 --- a/src/main/java/application/configuration/Configuration.java +++ b/src/main/java/application/configuration/Configuration.java @@ -83,6 +83,7 @@ private static String loadOneProperty(Properties properties, String propertyName Alert alert = new Alert( Alert.AlertType.ERROR, "Invalid properties file. Please delete the file" + HOME_DIRECTORY + properties_file); + alert.getDialogPane().getStylesheets().add(alert.getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); return ""; } diff --git a/src/main/java/application/project/controllers/ProjectDialogBox.java b/src/main/java/application/project/controllers/ProjectDialogBox.java index c683cec2..3d70d2c7 100644 --- a/src/main/java/application/project/controllers/ProjectDialogBox.java +++ b/src/main/java/application/project/controllers/ProjectDialogBox.java @@ -9,6 +9,7 @@ public static void projectCreationFailed() { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(Configuration.langBundle.getString("error")); alert.setHeaderText(Configuration.langBundle.getString("project_creating_error_occured")); + alert.getDialogPane().getStylesheets().add(alert.getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); } @@ -17,6 +18,7 @@ public static void projectLoadingFailed () { alert.setTitle(Configuration.langBundle.getString("error")); alert.setHeaderText(Configuration.langBundle.getString("project_loading_error_occured")); alert.setContentText(Configuration.langBundle.getString("project_loading_error_reason")); + alert.getDialogPane().getStylesheets().add(alert.getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); } @@ -24,6 +26,7 @@ public static void projectSavingFailed () { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(Configuration.langBundle.getString("error")); alert.setHeaderText(Configuration.langBundle.getString("project_saving_error_occured")); + alert.getDialogPane().getStylesheets().add(alert.getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); } } diff --git a/src/main/java/components/interviewPanel/Controllers/RichTextAreaController.java b/src/main/java/components/interviewPanel/Controllers/RichTextAreaController.java index 9b4a064f..9663c689 100644 --- a/src/main/java/components/interviewPanel/Controllers/RichTextAreaController.java +++ b/src/main/java/components/interviewPanel/Controllers/RichTextAreaController.java @@ -132,7 +132,8 @@ private void setUpPopUp() { popupMsg.setStyle( "-fx-background-color: black;" + "-fx-text-fill: white;" + - "-fx-padding: 5;"); + "-fx-padding: 5;" + + "-fx-font-family: serif;"); popup.getContent().add(popupMsg); area.setMouseOverTextDelay(Duration.ofMillis(500)); diff --git a/src/main/java/components/interviewPanel/ToolBar/tools/Controllers/ToolController.java b/src/main/java/components/interviewPanel/ToolBar/tools/Controllers/ToolController.java index 304cc418..fddda121 100644 --- a/src/main/java/components/interviewPanel/ToolBar/tools/Controllers/ToolController.java +++ b/src/main/java/components/interviewPanel/ToolBar/tools/Controllers/ToolController.java @@ -62,7 +62,7 @@ protected void initializeController() { protected void updateStyle() { if (selectedProperty.get()) { - label.setStyle("-fx-font-weight: bold"); + label.setStyle("-fx-font-weight: bold; -fx-font-family: serif;"); vbox.setStyle("-fx-border-color: black ; -fx-border-width: 1 ;"); SetGraphicsSelected(); } diff --git a/src/main/java/components/interviewSelector/controllers/InterviewSelectorCellController.java b/src/main/java/components/interviewSelector/controllers/InterviewSelectorCellController.java index e098e29d..6217e825 100644 --- a/src/main/java/components/interviewSelector/controllers/InterviewSelectorCellController.java +++ b/src/main/java/components/interviewSelector/controllers/InterviewSelectorCellController.java @@ -43,6 +43,7 @@ public void initialize(URL url, ResourceBundle resourceBundle) { alert.setTitle(Configuration.langBundle.getString("confirmation_dialog")); alert.setHeaderText(Configuration.langBundle.getString("delete_interview")); alert.setContentText(Configuration.langBundle.getString("continue_alert")); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); Optional result = alert.showAndWait(); if (result.isPresent() && result.get() == ButtonType.OK){ commandFactory.deleteInterview(interview).execute(); diff --git a/src/main/java/components/mainView/controller/MainViewController.java b/src/main/java/components/mainView/controller/MainViewController.java index 3265e856..fcbcb9db 100644 --- a/src/main/java/components/mainView/controller/MainViewController.java +++ b/src/main/java/components/mainView/controller/MainViewController.java @@ -23,7 +23,7 @@ import application.configuration.AppSettings; import components.schemaTree.Services.categoryUsesCounter.SchemaCategoryUsesCounter; import components.schemaTree.Services.propertyUsesCounter.SchemaPropertyUsesCounter; -import components.templateSpace.controllers.TemplateSpaceController; +import components.toolbox.controllers.ToolBoxControllers; import javafx.scene.layout.HBox; import models.Project; import models.Interview; @@ -40,6 +40,7 @@ import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.layout.VBox; +import models.SchemaFolder; import java.io.IOException; import java.net.URL; @@ -53,7 +54,7 @@ public class MainViewController implements Initializable { private @FXML SplitPane leftPane; private @FXML HBox paneOfTextArea; private @FXML ModelisationSpaceController modelisationSpaceController; - private @FXML TemplateSpaceController templateSpaceController; + private @FXML ToolBoxControllers toolBox; private @FXML HBox modelMomentBox; private @FXML Button btnZoomMinus; private @FXML Button btnZoomPlus; @@ -64,6 +65,7 @@ public class MainViewController implements Initializable { private InterviewSelectorController interviewSelector; private InterviewPanelController interviewPanel; + private ToolBoxControllers toolBoxControllers; private ChangeListener onSelectedInterviewChanges = (observableValue, o, t1) -> { if(t1 != null){ @@ -143,6 +145,9 @@ private void refreshContent() { mainSplitPane.setDividerPosition(1,0.7); }))); + // Initialisation de la ToolBox avec tout ce qui suit (TemplateSpaceController) + ToolBoxControllers toolBoxControllers = ToolBoxControllers.getToolBoxControllersInstance(project); + toolBox.getChildren().add(toolBoxControllers.createToolBoxControllers(toolBoxControllers)); } @Override diff --git a/src/main/java/components/modelisationSpace/category/appCommands/AddConcreteCategoryCommand.java b/src/main/java/components/modelisationSpace/category/appCommands/AddConcreteCategoryCommand.java index a2d6b12c..8b7d03c9 100644 --- a/src/main/java/components/modelisationSpace/category/appCommands/AddConcreteCategoryCommand.java +++ b/src/main/java/components/modelisationSpace/category/appCommands/AddConcreteCategoryCommand.java @@ -2,7 +2,6 @@ import application.history.HistoryManager; import application.history.ModelUserActionCommandHooks; -import components.modelisationSpace.hooks.ModelisationSpaceHook; import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; import models.ConcreteCategory; import components.modelisationSpace.category.modelCommands.AddConcreteCategory; @@ -21,24 +20,25 @@ public class AddConcreteCategoryCommand implements Executable { public Void execute() { AddConcreteCategory cmd = new AddConcreteCategory(parent, category); if(hookNotifier != null) { - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> { hookNotifier.notifyConcreteCategoryAdded(category); }); - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> { hookNotifier.notifyConcreteCategoryRemoved(category); }); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> hookNotifier.notifyConcreteCategoryAdded(category)); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> hookNotifier.notifyConcreteCategoryRemoved(category)); } HistoryManager.addCommand(cmd, userCommand); return null; } - public AddConcreteCategoryCommand(Moment parent, ConcreteCategory category, boolean userCommand) { + public AddConcreteCategoryCommand(ModelisationSpaceHookNotifier hookNotifier, Moment parent, SchemaCategory category, boolean userCommand) { + this.hookNotifier = hookNotifier; this.parent = parent; - this.category = category; + this.category = new ConcreteCategory(category); this.userCommand = userCommand; } - public AddConcreteCategoryCommand(ModelisationSpaceHookNotifier hookNotifier, Moment parent, SchemaCategory category, boolean userCommand) { + public AddConcreteCategoryCommand(ModelisationSpaceHookNotifier hookNotifier, Moment parent, ConcreteCategory category, boolean userCommand) { this.hookNotifier = hookNotifier; this.parent = parent; - this.category = new ConcreteCategory(category); + this.category = category; this.userCommand = userCommand; } } diff --git a/src/main/java/components/modelisationSpace/category/appCommands/ConcreteCategoryCommandFactory.java b/src/main/java/components/modelisationSpace/category/appCommands/ConcreteCategoryCommandFactory.java index 28b5daae..3378bc48 100644 --- a/src/main/java/components/modelisationSpace/category/appCommands/ConcreteCategoryCommandFactory.java +++ b/src/main/java/components/modelisationSpace/category/appCommands/ConcreteCategoryCommandFactory.java @@ -15,7 +15,7 @@ public ConcreteCategoryCommandFactory(ModelisationSpaceHookNotifier hookNotifier this.parent = parent; } - public AddConcreteCategoryCommand addConcreteCategoryCommand(ConcreteCategory c, boolean userCommand) { return new AddConcreteCategoryCommand(parent, c, userCommand); } + public AddConcreteCategoryCommand addConcreteCategoryCommand(ConcreteCategory c, boolean userCommand) { return new AddConcreteCategoryCommand(hookNotifier, parent, c, userCommand); } public AddConcreteCategoryCommand addSchemaCategoryCommand(SchemaCategory sc, boolean userCommand) { return new AddConcreteCategoryCommand(hookNotifier, parent, sc, userCommand); } public RemoveConcreteCategoryCommand removeConcreteCategoryCommand(ConcreteCategory c, boolean userCommand) { return new RemoveConcreteCategoryCommand(hookNotifier, parent, c, c.getController(), userCommand); } diff --git a/src/main/java/components/modelisationSpace/category/appCommands/RemoveConcreteCategoryCommand.java b/src/main/java/components/modelisationSpace/category/appCommands/RemoveConcreteCategoryCommand.java index 2c50b217..3a450eee 100644 --- a/src/main/java/components/modelisationSpace/category/appCommands/RemoveConcreteCategoryCommand.java +++ b/src/main/java/components/modelisationSpace/category/appCommands/RemoveConcreteCategoryCommand.java @@ -1,6 +1,7 @@ package components.modelisationSpace.category.appCommands; import application.history.HistoryManager; +import application.history.ModelUserActionCommandHooks; import components.modelisationSpace.category.controllers.ConcreteCategoryController; import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; import models.ConcreteCategory; @@ -26,8 +27,13 @@ public RemoveConcreteCategoryCommand(ModelisationSpaceHookNotifier hooksNotifier @Override public Void execute() { - HistoryManager.addCommand(new RemoveConcreteCategory(parent, category, controller), userCommand); - hooksNotifier.notifyConcreteCategoryRemoved(category); + RemoveConcreteCategory cmd = new RemoveConcreteCategory(parent, category, controller); + if(hooksNotifier != null) { + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> hooksNotifier.notifyConcreteCategoryRemoved(category)); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> hooksNotifier.notifyConcreteCategoryAdded(category)); + } + HistoryManager.addCommand(cmd, userCommand); + return null; } } diff --git a/src/main/java/components/modelisationSpace/category/modelCommands/RemoveConcreteCategory.java b/src/main/java/components/modelisationSpace/category/modelCommands/RemoveConcreteCategory.java index 327a2235..2a9df463 100644 --- a/src/main/java/components/modelisationSpace/category/modelCommands/RemoveConcreteCategory.java +++ b/src/main/java/components/modelisationSpace/category/modelCommands/RemoveConcreteCategory.java @@ -9,13 +9,11 @@ public class RemoveConcreteCategory extends ModelUserActionCommand { private Moment moment; private ConcreteCategory concreteCategory; - int prevIndex; private ConcreteCategoryController controller; public RemoveConcreteCategory(Moment m, ConcreteCategory c, ConcreteCategoryController controller) { this.moment = m; this.concreteCategory = c; - this.prevIndex = moment.indexOfConcreteCategory(concreteCategory); this.controller = controller; } @@ -38,7 +36,7 @@ public Void execute() { @Override public Void undo() { - moment.addCategory(prevIndex, concreteCategory); + moment.addCategory(concreteCategory); // Add the underlining of the descripteme deleted concreteCategory.getJustification().descriptemesProperty().forEach(descripteme -> { diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/AddSiblingMomentCommand.java b/src/main/java/components/modelisationSpace/moment/appCommands/AddSiblingMomentCommand.java index 7823c7e3..583e9ce2 100644 --- a/src/main/java/components/modelisationSpace/moment/appCommands/AddSiblingMomentCommand.java +++ b/src/main/java/components/modelisationSpace/moment/appCommands/AddSiblingMomentCommand.java @@ -1,18 +1,14 @@ package components.modelisationSpace.moment.appCommands; -import application.configuration.Configuration; import application.history.HistoryManager; import application.history.ModelUserActionCommandHooks; import components.modelisationSpace.category.appCommands.AddConcreteCategoryCommand; import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; import components.modelisationSpace.justification.appCommands.AddDescriptemeCommand; -import models.*; import components.modelisationSpace.moment.modelCommands.AddSubMoment; -import utils.DialogState; -import utils.autoSuggestion.strategies.SuggestionStrategyMoment; +import models.*; import utils.command.Executable; -import utils.popups.TextEntryController; public class AddSiblingMomentCommand implements Executable { @@ -23,6 +19,7 @@ public class AddSiblingMomentCommand implements Executable { private ConcreteCategory concreteCategory; int index = -1; private ModelisationSpaceHookNotifier hooksNotifier; + private Boolean isRenaming = true; public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment newMoment, ConcreteCategory concreteCategory) { this.hooksNotifier = hooksNotifier; @@ -69,6 +66,23 @@ public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, Root concreteCategory = null; } + public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment newMoment, int index, boolean isRenaming) { + this.hooksNotifier = hooksNotifier; + this.parent = parent; + this.newMoment = newMoment; + this.index = index; + this.isRenaming = isRenaming; + concreteCategory = null; + } + + public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment newMoment, boolean isRenaming) { + this.hooksNotifier = hooksNotifier; + this.parent = parent; + this.newMoment = newMoment; + this.isRenaming = isRenaming; + concreteCategory = null; + } + public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment newMoment, Descripteme descripteme) { this.hooksNotifier = hooksNotifier; this.parent = parent; @@ -86,8 +100,6 @@ public AddSiblingMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, Root @Override public Void execute() { - String name = Configuration.langBundle.getString("new_moment"); - //Model command creation AddSubMoment cmd; if(index == -1) @@ -99,7 +111,7 @@ public Void execute() { HistoryManager.addCommand(cmd, true); if (concreteCategory != null) { - new AddConcreteCategoryCommand(newMoment, concreteCategory, false).execute(); + new AddConcreteCategoryCommand(hooksNotifier, newMoment, concreteCategory, false).execute(); } else if(schemaCategory != null) { new AddConcreteCategoryCommand(hooksNotifier, newMoment, schemaCategory, false).execute(); @@ -110,7 +122,9 @@ else if (descripteme != null) { newMoment.addParent(parent); - newMoment.getController().passInRenamingMode(true); + if (this.isRenaming) { + newMoment.getController().passInRenamingMode(true); + } return null; } diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/ChangeColorMomentCommand.java b/src/main/java/components/modelisationSpace/moment/appCommands/ChangeColorMomentCommand.java index d288a87a..6867fcf8 100644 --- a/src/main/java/components/modelisationSpace/moment/appCommands/ChangeColorMomentCommand.java +++ b/src/main/java/components/modelisationSpace/moment/appCommands/ChangeColorMomentCommand.java @@ -4,12 +4,8 @@ import application.configuration.Configuration; import application.history.HistoryManager; import components.modelisationSpace.moment.modelCommands.ChangeColorMoment; -import components.modelisationSpace.moment.modelCommands.RenameMoment; import models.Moment; -import utils.DialogState; -import utils.autoSuggestion.strategies.SuggestionStrategyMoment; import utils.command.Executable; -import utils.popups.TextEntryController; import utils.popups.WarningPopup; public class ChangeColorMomentCommand implements Executable { diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/DeleteMomentCommand.java b/src/main/java/components/modelisationSpace/moment/appCommands/DeleteMomentCommand.java index 7bf1a753..505fd37d 100644 --- a/src/main/java/components/modelisationSpace/moment/appCommands/DeleteMomentCommand.java +++ b/src/main/java/components/modelisationSpace/moment/appCommands/DeleteMomentCommand.java @@ -14,19 +14,21 @@ public class DeleteMomentCommand implements Executable { ModelisationSpaceHookNotifier hooksNotifier; RootMoment parent; Moment moment; + boolean userCommand; - public DeleteMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment m) { + public DeleteMomentCommand(ModelisationSpaceHookNotifier hooksNotifier, RootMoment parent, Moment m, boolean userCommand) { this.hooksNotifier = hooksNotifier; this.parent = parent; this.moment = m; + this.userCommand = userCommand; } @Override public Void execute() { RemoveSubMoment cmd = new RemoveSubMoment(parent, moment); - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> { hooksNotifier.notifyMomentRemoved(moment); }); - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> { hooksNotifier.notifyMomentAdded(moment); }); - HistoryManager.addCommand(cmd, true); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> hooksNotifier.notifyMomentRemoved(moment)); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> hooksNotifier.notifyMomentAdded(moment)); + HistoryManager.addCommand(cmd, userCommand); return null; } diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/MergeMomentCommand.java b/src/main/java/components/modelisationSpace/moment/appCommands/MergeMomentCommand.java new file mode 100644 index 00000000..f9797837 --- /dev/null +++ b/src/main/java/components/modelisationSpace/moment/appCommands/MergeMomentCommand.java @@ -0,0 +1,149 @@ +package components.modelisationSpace.moment.appCommands; + +import application.configuration.Configuration; +import components.modelisationSpace.category.appCommands.AddConcreteCategoryCommand; +import components.modelisationSpace.category.appCommands.RemoveConcreteCategoryCommand; +import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; +import components.modelisationSpace.justification.appCommands.AddDescriptemeCommand; +import models.ConcreteCategory; +import models.Moment; +import utils.DialogState; +import utils.command.Executable; +import utils.popups.MergerPopup; +import utils.popups.WarningPopup; + +import java.util.ArrayList; + + +public class MergeMomentCommand implements Executable { + private ModelisationSpaceHookNotifier hookNotifier; + private Moment destinationMoment; + private Moment sourceMoment; + private boolean userCommand; + + + + public MergeMomentCommand(ModelisationSpaceHookNotifier hookNotifier, Moment destinationMoment, Moment sourceMoment, boolean userCommand) { + this.hookNotifier = hookNotifier; + this.destinationMoment = destinationMoment; + this.sourceMoment = sourceMoment; + this.userCommand = userCommand; + } + + public StringBuilder buildRemplacementCategoryMessage(ConcreteCategory sourceCategory, ConcreteCategory destinationCategory) { + StringBuilder message = new StringBuilder(); + sourceCategory.propertiesProperty().forEach(sourceProperty -> { + int sourcePropertyIndex = sourceCategory.propertiesProperty().indexOf(sourceProperty); + String destinationPropertyValue = destinationCategory.propertiesProperty().get(sourcePropertyIndex).getValue(); + + if (sourceProperty.getValue().equals(destinationPropertyValue)) return; + + + message.append("\t- ").append(sourceProperty.getName()).append(" : "); + message.append('"').append(destinationPropertyValue).append('"'); + message.append(' ').append(Configuration.langBundle.getString("merge_be_replaced")).append(' '); + message.append('"').append(sourceProperty.getValue()).append("\"\n"); + }); + if (message.toString().isEmpty()) { + message.append('\t').append(Configuration.langBundle.getString("merge_empty_category_replacement")).append('\n'); + } + return message; + } + + private boolean confirmationMessage() { + StringBuilder message = new StringBuilder(); + + //information part + message.append(Configuration.langBundle.getString("merge_information_p1")) + .append(" \"").append(sourceMoment.getName()).append("\" ") + .append(Configuration.langBundle.getString("merge_information_p2")) + .append(" \"").append(destinationMoment.getName()).append("\".\n\n"); + + //add part + message.append(Configuration.langBundle.getString("merge_add_info")) + .append(" \"").append(destinationMoment.getName()).append("\" :\n"); + + message.append("\t- ").append(Configuration.langBundle.getString("merge_add_moment_descriptem")) + .append(" \"").append(sourceMoment.getName()).append("\"\n"); + + + ArrayList categoryNames = new ArrayList<>(); + sourceMoment.concreteCategoriesProperty().forEach(category -> { + if (!destinationMoment.hadThisCategory(category)) { + categoryNames.add(category.getName()); + } + }); + + if (!categoryNames.isEmpty()){ + String ctgNames = categoryNames.toString(); + ctgNames = ctgNames.substring(1, ctgNames.length()-1); + + if (categoryNames.size() == 1) { + message.append("\t- ").append(Configuration.langBundle.getString("merge_add_category_p1")) + .append(' ').append(ctgNames).append(' ') + .append(Configuration.langBundle.getString("merge_add_category_p2")).append('\n'); + } + else { + message.append("\t- ").append(Configuration.langBundle.getString("merge_add_category_p1_pluriel")) + .append(' ').append(ctgNames).append(' ') + .append(Configuration.langBundle.getString("merge_add_category_p2_pluriel")).append('\n'); + } + } + message.append('\n'); + + //replacement part + sourceMoment.concreteCategoriesProperty().forEach(category -> { + if (!destinationMoment.hadThisCategory(category)) return; + + ConcreteCategory destinationCategory = destinationMoment.getCategory(category); + + //message for category to replace + StringBuilder cc = buildRemplacementCategoryMessage(category, destinationCategory); + message.append(Configuration.langBundle.getString("merge_add_category_p1")).append(' ') + .append(category.getName()).append(' ') + .append(Configuration.langBundle.getString("merge_merge_category")).append(' ') + .append(sourceMoment.getName()).append(" :\n").append(cc).append('\n'); + }); + + //end part + message.append(Configuration.langBundle.getString("merge_confirmation")); + MergerPopup mp = MergerPopup.display(message.toString()); + return mp.getState() == DialogState.SUCCESS; + } + + @Override + public Void execute() { + if (!sourceMoment.momentsProperty().isEmpty()) { + WarningPopup.display(Configuration.langBundle.getString("merge_warning")); + return null; + } + + //show message and wait user to confirm the merge + if (!confirmationMessage()) return null; + + + //Copy descriptemes + sourceMoment.getJustification().descriptemesProperty().forEach(descripteme -> { + new AddDescriptemeCommand(destinationMoment.getJustification(), descripteme, userCommand).execute(); + if (userCommand) userCommand = false; + }); + + + //Copy categories + sourceMoment.concreteCategoriesProperty().forEach(category -> { + if (destinationMoment.hadThisCategory(category)) { + //delete old category + ConcreteCategory destinationCC = destinationMoment.getCategory(category); + new RemoveConcreteCategoryCommand(hookNotifier, destinationMoment, destinationCC, destinationCC.getController(), userCommand).execute(); + } + new AddConcreteCategoryCommand(hookNotifier, destinationMoment, category, userCommand).execute(); + + if (userCommand) userCommand = false; + }); + + //Delete moment + new DeleteMomentCommand(hookNotifier,sourceMoment.getParent(), sourceMoment, userCommand).execute(); + + return null; + } +} diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/MomentCommandFactory.java b/src/main/java/components/modelisationSpace/moment/appCommands/MomentCommandFactory.java index c650cd9b..2977ecd3 100644 --- a/src/main/java/components/modelisationSpace/moment/appCommands/MomentCommandFactory.java +++ b/src/main/java/components/modelisationSpace/moment/appCommands/MomentCommandFactory.java @@ -6,7 +6,6 @@ import models.RootMoment; import models.SchemaCategory; import models.Descripteme; -import utils.command.Executable; public class MomentCommandFactory { @@ -25,6 +24,13 @@ public AddSiblingMomentCommand addSiblingCommand(Moment m) { return new AddSiblingMomentCommand(hookNotifier, parent, m); } + public AddSiblingMomentCommand addSiblingCommand(Moment m, int index, boolean isRenaming) { + return new AddSiblingMomentCommand(hookNotifier, parent, m, index, isRenaming); + } + public AddSiblingMomentCommand addSiblingCommand(Moment m, boolean isRenaming) { + return new AddSiblingMomentCommand(hookNotifier, parent, m, isRenaming); + } + public AddSiblingMomentCommand addSiblingCommand(Moment m, ConcreteCategory category) { return new AddSiblingMomentCommand(hookNotifier, parent, m, category); @@ -46,7 +52,7 @@ public MoveMomentCommand moveMomentCommand(Moment m, RootMoment originParent, in public MoveMomentCommand moveMomentCommand(Moment m, RootMoment originParent){ return new MoveMomentCommand(parent, originParent, m); } - public DeleteMomentCommand deleteCommand(Moment m) { return new DeleteMomentCommand(hookNotifier, parent, m); } + public DeleteMomentCommand deleteCommand(Moment m) { return new DeleteMomentCommand(hookNotifier, parent, m, true); } public SetMomentTransCommand transitionCommand(Moment m) { return new SetMomentTransCommand(m); } public AddCommentCommand addCommentCommand(Moment m, String comment){ return new AddCommentCommand(m, comment);} @@ -63,7 +69,11 @@ public AddSiblingMomentCommand addSiblingCommand(Moment m, Descripteme descripte return new AddSiblingMomentCommand(hookNotifier, parent, m, descripteme, index); } - public Executable colorCommand(Moment m, String color) { + public ChangeColorMomentCommand colorCommand(Moment m, String color) { return new ChangeColorMomentCommand(m, color); } + + public MergeMomentCommand mergeMomentCommand(Moment destinationMoment, Moment sourceMoment, boolean userCommand) { + return new MergeMomentCommand(hookNotifier, destinationMoment, sourceMoment, userCommand); + } } diff --git a/src/main/java/components/modelisationSpace/moment/appCommands/MoveMomentCommand.java b/src/main/java/components/modelisationSpace/moment/appCommands/MoveMomentCommand.java index dc21fc12..e10371f5 100644 --- a/src/main/java/components/modelisationSpace/moment/appCommands/MoveMomentCommand.java +++ b/src/main/java/components/modelisationSpace/moment/appCommands/MoveMomentCommand.java @@ -1,10 +1,12 @@ package components.modelisationSpace.moment.appCommands; +import application.configuration.Configuration; import application.history.HistoryManager; import components.modelisationSpace.moment.modelCommands.MoveMoment; import models.Moment; import models.RootMoment; import utils.command.Executable; +import utils.popups.WarningPopup; public class MoveMomentCommand implements Executable { RootMoment parent; @@ -25,8 +27,27 @@ public MoveMomentCommand(RootMoment parent, RootMoment originParent, Moment m) { this.moment = m; } + private boolean submomentIsParent(Moment m) { + if (m.equals(parent)) { + return true; + } + else { + if (m.numberOfSubMoments() > 0) { + for (Moment submoment : m.momentsProperty()) { + if (submomentIsParent(submoment)) return true; + } + } + return false; + } + } @Override public Void execute() { + if (submomentIsParent(moment)) { + WarningPopup.display(Configuration.langBundle.getString("move_under_submoment_warning")); + return null; + } + + MoveMoment cmd; if(index == -1) cmd = new MoveMoment(parent, originParent, moment); diff --git a/src/main/java/components/modelisationSpace/moment/controllers/MomentController.java b/src/main/java/components/modelisationSpace/moment/controllers/MomentController.java index d9d39c95..800b28a1 100644 --- a/src/main/java/components/modelisationSpace/moment/controllers/MomentController.java +++ b/src/main/java/components/modelisationSpace/moment/controllers/MomentController.java @@ -2,51 +2,44 @@ import application.configuration.Configuration; import application.history.HistoryManager; -import components.modelisationSpace.controllers.ModelisationSpaceController; -import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.scene.control.*; -import javafx.scene.image.ImageView; -import javafx.scene.image.Image; -import javafx.scene.input.*; -import javafx.scene.paint.Color; -import javafx.scene.text.Text; -import javafx.scene.text.TextAlignment; -import models.Descripteme; import components.modelisationSpace.appCommand.ScrollPaneCommandFactory; import components.modelisationSpace.category.appCommands.ConcreteCategoryCommandFactory; import components.modelisationSpace.category.controllers.ConcreteCategoryController; -import models.ConcreteCategory; +import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; import components.modelisationSpace.justification.controllers.JustificationController; import components.modelisationSpace.moment.appCommands.MomentCommandFactory; -import models.Moment; -import models.SchemaCategory; import components.modelisationSpace.moment.modelCommands.RenameMoment; import javafx.animation.KeyFrame; import javafx.animation.Timeline; +import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.*; import javafx.scene.layout.*; +import javafx.scene.paint.Color; import javafx.util.Duration; +import models.ConcreteCategory; +import models.Descripteme; +import models.Moment; +import models.SchemaCategory; import utils.autoSuggestion.AutoSuggestionsTextField; import utils.autoSuggestion.strategies.SuggestionStrategyMoment; import utils.dragAndDrop.DragStore; import utils.modelControllers.ListView.ListView; import utils.modelControllers.ListView.ListViewController; import utils.modelControllers.ListView.ListViewUpdate; -import utils.popups.TextEntryController; import utils.popups.WarningPopup; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; +import java.util.Comparator; import java.util.ResourceBundle; @@ -102,6 +95,7 @@ public class MomentController extends ListViewController implements Init public MomentController(Moment m, MomentCommandFactory cmdFactory, ScrollPaneCommandFactory paneCmdFactory) { this.moment = m; + m.setController(this); this.cmdFactory = cmdFactory; this.categoryCmdFactory = new ConcreteCategoryCommandFactory(cmdFactory.getHookNotifier(), moment); this.childCmdFactory = new MomentCommandFactory(cmdFactory.getHookNotifier(), moment); @@ -163,6 +157,7 @@ public void initialize(URL url, ResourceBundle resourceBundle) { // category -> { cmdFactory.addSiblingCommand(new Moment("Moment"), category, 0).execute(); } separatorBottom.setOnDragMomentDone((moment, originParent) -> childCmdFactory.moveMomentCommand(moment, originParent).execute()); separatorBottom.setOnDragTemplateMomentDone(templateMoment -> childCmdFactory.addSiblingCommand(templateMoment.createConcreteMoment()).execute()); + separatorBottom.setOnDragSchemaMomentType(schemaMomentType -> childCmdFactory.addSiblingCommand(schemaMomentType.createMoment(), false).execute()); //Menu Button if (commentArea.isVisible()) { @@ -202,7 +197,6 @@ public void initialize(URL url, ResourceBundle resourceBundle) { } catch (Error error) { WarningPopup.display(Configuration.langBundle.getString("transitional_warning")); } - displayTransitional(); }); menuButton.getItems().add(transitionButton); grid.add(transitionPane, 1, 1); @@ -242,11 +236,12 @@ private void collapseOrNot() { // hide categories // when the moment is collapsed, there is only the moment names displayed VBox categoryNames = new VBox(); - categoryNames.setStyle("-fx-background-color: #ffffff;\n" + - "-fx-border-color: transparent;\n" + - "-fx-background-insets: 1px;\n" + - "-fx-background-radius: 3;\n" + - "-fx-border-radius:3;"); + categoryNames.setStyle("-fx-background-color: #ffffff;" + + "-fx-border-color: transparent;" + + "-fx-background-insets: 1px;" + + "-fx-background-radius: 3;" + + "-fx-border-radius:3;" + + "-fx-font-family: serif;"); moment.concreteCategoriesProperty().forEach((category) -> categoryNames.getChildren().add(new Label(category.getName()))); momentContainer.setBottom(categoryNames); } @@ -315,6 +310,8 @@ private void addJustifications() { } private void addCategories() { + moment.concreteCategoriesProperty().sort(Comparator.comparing(ConcreteCategory::getName)); + categories = new ListView<>( moment.concreteCategoriesProperty(), (cc -> new ConcreteCategoryController(cc, categoryCmdFactory, paneCmdFactory)), @@ -359,7 +356,7 @@ public void passInRenamingMode(boolean YoN) { } } - private void displayTransitional() { + public void displayTransitional() { double depth; String color = getTransitionColor(); transitionBox.setMaxHeight(0); @@ -414,6 +411,11 @@ private void updateBorders(int index, int siblingsCount) { separatorLeft.setOnDragDoneShemaCategory(category -> cmdFactory.addSiblingCommand(new Moment("Moment"), category, this.moment, 0).execute()); separatorRight.setOnDragDoneShemaCategory(category -> cmdFactory.addSiblingCommand(new Moment("Moment"), category, this.moment, index+1).execute()); + separatorLeft.setOnDragSchemaMomentType(schemaMomentType -> cmdFactory.addSiblingCommand(schemaMomentType.createMoment(), 0, false).execute()); + separatorRight.setOnDragSchemaMomentType(schemaMomentType -> cmdFactory.addSiblingCommand(schemaMomentType.createMoment(), index+1, false).execute()); + + + if(index == 0) { //Hide an show the separators if(!grid.getChildren().contains(separatorLeft.getNode())) @@ -446,15 +448,18 @@ private void updateBorders(int index, int siblingsCount) { separatorLeft.setOnDragDoneDescripteme(descripteme -> {}); separatorLeft.setOnDragMomentDone((m, factory) -> {}); separatorLeft.setOnDragTemplateMomentDone(templateMoment -> {}); + if(index == siblingsCount - 1) { separatorRight.setOnDragDoneDescripteme(descripteme -> cmdFactory.addSiblingCommand(new Moment("Moment"), descripteme).execute()); separatorRight.setOnDragMomentDone((m, originParent) -> cmdFactory.moveMomentCommand(m, originParent).execute()); separatorRight.setOnDragTemplateMomentDone(templateMoment -> cmdFactory.addSiblingCommand(templateMoment.createConcreteMoment()).execute()); + } else { separatorRight.setOnDragDoneDescripteme(descripteme -> cmdFactory.addSiblingCommand(new Moment("Moment"), descripteme, index+1).execute()); separatorRight.setOnDragMomentDone((m,originParent) -> cmdFactory.moveMomentCommand(m, originParent, index + 1).execute()); separatorRight.setOnDragTemplateMomentDone(templateMoment -> cmdFactory.addSiblingCommand(templateMoment.createConcreteMoment(), index+1).execute()); + } //Make moment aligned, no need to understand that ! @@ -495,6 +500,14 @@ else if ( dragEvent.acceptTransferModes(TransferMode.MOVE); dragEvent.consume(); } + //Moment + else if ( + DragStore.getDraggable().getDataFormat() == Moment.format + && !moment.equals(DragStore.getDraggable()) + ) { + dragEvent.acceptTransferModes(TransferMode.MOVE); + dragEvent.consume(); + } } }); @@ -517,12 +530,16 @@ else if(DragStore.getDraggable().getDataFormat() == ConcreteCategory.format) { dragEvent.setDropCompleted(true); dragEvent.consume(); } + else if(DragStore.getDraggable().getDataFormat() == Moment.format) { + cmdFactory.mergeMomentCommand(moment, DragStore.getDraggable(), true).execute(); + dragEvent.setDropCompleted(true); + dragEvent.consume(); + } }); momentContainer.setOnDragExited(dragEvent -> categoryDropper.setStyle("-fx-opacity: 1;")); momentContainer.setOnDragDetected(event -> { - System.out.println(" moment drag detected"); Dragboard db = momentContainer.startDragAndDrop(TransferMode.MOVE); ClipboardContent content = new ClipboardContent(); content.put(moment.getDataFormat(), 0); diff --git a/src/main/java/components/modelisationSpace/moment/controllers/MomentSeparatorController.java b/src/main/java/components/modelisationSpace/moment/controllers/MomentSeparatorController.java index bfea3e55..1124d6e3 100644 --- a/src/main/java/components/modelisationSpace/moment/controllers/MomentSeparatorController.java +++ b/src/main/java/components/modelisationSpace/moment/controllers/MomentSeparatorController.java @@ -1,11 +1,10 @@ package components.modelisationSpace.moment.controllers; +import models.SchemaMomentType; import javafx.application.Platform; -import models.*; -import components.modelisationSpace.moment.appCommands.MomentCommandFactory; -import javafx.scene.input.DataFormat; import javafx.scene.input.TransferMode; import javafx.scene.layout.Pane; +import models.*; import utils.dragAndDrop.DragStore; import java.util.function.BiConsumer; @@ -23,6 +22,7 @@ public class MomentSeparatorController { private Consumer onDragDoneShemaCategory = category -> {}; private BiConsumer onDragMomentDone = (moment, originParentMoment) -> { }; private Consumer onDragTemplateMoment = templateMoment -> {}; + private Consumer onDragSchemaMomentType = schemaMomentType -> {}; public MomentSeparatorController(boolean vertical) { p = new Pane(); @@ -80,6 +80,11 @@ else if(DragStore.getDraggable().isDraggable() && DragStore.getDraggable().getDa dragEvent.consume(); Platform.runLater(() -> { onDragTemplateMoment.accept(DragStore.getDraggable()); }); } + else if(DragStore.getDraggable().isDraggable() && DragStore.getDraggable().getDataFormat() == SchemaMomentType.format && active){ + dragEvent.setDropCompleted(true); + dragEvent.consume(); + Platform.runLater(() -> { onDragSchemaMomentType.accept(DragStore.getDraggable()); }); + } } }); @@ -110,6 +115,9 @@ public void setOnDragMomentDone(BiConsumerconsumer){ public void setOnDragTemplateMomentDone(Consumer consumer) { this.onDragTemplateMoment = consumer; } + public void setOnDragSchemaMomentType(Consumer consumer) { + this.onDragSchemaMomentType = consumer; + } public Pane getNode() { return p; @@ -121,7 +129,7 @@ private boolean acceptDnDElementFormat() { || DragStore.getDraggable().getDataFormat() == SchemaCategory.format || DragStore.getDraggable().getDataFormat() == Moment.format || DragStore.getDraggable().getDataFormat() == TemplateMoment.format - + || DragStore.getDraggable().getDataFormat() == SchemaMomentType.format ); } } diff --git a/src/main/java/components/modelisationSpace/moment/modelCommands/MoveMoment.java b/src/main/java/components/modelisationSpace/moment/modelCommands/MoveMoment.java index 5653b2e4..77070962 100644 --- a/src/main/java/components/modelisationSpace/moment/modelCommands/MoveMoment.java +++ b/src/main/java/components/modelisationSpace/moment/modelCommands/MoveMoment.java @@ -33,6 +33,9 @@ public Void execute() { parent.addMoment(moment); } else { + if (originParent.equals(parent) && originIndex < addIndex) { + addIndex -= 1; + } parent.addMoment(addIndex, moment); } return null; @@ -41,7 +44,9 @@ public Void execute() { @Override public Void undo() { parent.removeMoment(moment); - originParent.addMoment(originIndex, moment); + if (originIndex != -1) { + originParent.addMoment(originIndex, moment); + } return null; } } diff --git a/src/main/java/components/modelisationSpace/moment/modelCommands/SetMomentTrans.java b/src/main/java/components/modelisationSpace/moment/modelCommands/SetMomentTrans.java index b80ca840..3ef134e3 100644 --- a/src/main/java/components/modelisationSpace/moment/modelCommands/SetMomentTrans.java +++ b/src/main/java/components/modelisationSpace/moment/modelCommands/SetMomentTrans.java @@ -18,12 +18,14 @@ public SetMomentTrans(Moment m, boolean oldstate) { public Object execute() { newstate = !oldstate; moment.setTransitional(newstate); + moment.getController().displayTransitional(); return null; } @Override public Object undo() { moment.setTransitional(oldstate); + moment.getController().displayTransitional(); return null; } diff --git a/src/main/java/components/modelisationSpace/property/appCommands/EditConcretePropertyCommand.java b/src/main/java/components/modelisationSpace/property/appCommands/EditConcretePropertyCommand.java new file mode 100644 index 00000000..09e4f3d7 --- /dev/null +++ b/src/main/java/components/modelisationSpace/property/appCommands/EditConcretePropertyCommand.java @@ -0,0 +1,37 @@ +package components.modelisationSpace.property.appCommands; + +import application.history.HistoryManager; +import application.history.ModelUserActionCommandHooks; +import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; +import components.modelisationSpace.property.modelCommands.EditConcretePropertyValue; +import models.ConcreteProperty; +import utils.command.Executable; + +public class EditConcretePropertyCommand implements Executable { + private ModelisationSpaceHookNotifier hooksNotifier; + private ConcreteProperty property; + private String newValue; + private boolean userCommand; + + public EditConcretePropertyCommand(ModelisationSpaceHookNotifier hooksNotifier, ConcreteProperty property, String newValue, boolean userCommand) { + this.hooksNotifier = hooksNotifier; + this.property = property; + this.newValue = newValue; + this.userCommand = userCommand; + } + + @Override + public Void execute() { + EditConcretePropertyValue cmd = new EditConcretePropertyValue(property, newValue); + + if(hooksNotifier != null) { + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> hooksNotifier.notifyConcretePropertyValueChanged(property.getValue(), property)); + cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> hooksNotifier.notifyConcretePropertyValueChanged(newValue, property)); + } + + HistoryManager.addCommand(cmd, userCommand); + return null; + } +} + + diff --git a/src/main/java/components/modelisationSpace/property/controllers/ConcretePropertyController.java b/src/main/java/components/modelisationSpace/property/controllers/ConcretePropertyController.java index f7acff75..2463344e 100644 --- a/src/main/java/components/modelisationSpace/property/controllers/ConcretePropertyController.java +++ b/src/main/java/components/modelisationSpace/property/controllers/ConcretePropertyController.java @@ -1,14 +1,15 @@ package components.modelisationSpace.property.controllers; import application.configuration.Configuration; -import application.history.HistoryManager; -import application.history.ModelUserActionCommandHooks; -import components.modelisationSpace.hooks.ModelisationSpaceHook; import components.modelisationSpace.hooks.ModelisationSpaceHookNotifier; +import components.modelisationSpace.property.appCommands.EditConcretePropertyCommand; +import javafx.geometry.Pos; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; import models.Descripteme; import components.modelisationSpace.justification.controllers.JustificationController; import models.ConcreteProperty; -import components.modelisationSpace.property.modelCommands.EditConcretePropertyValue; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; @@ -19,12 +20,11 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; -import utils.DialogState; -import utils.autoSuggestion.strategies.SuggestionStrategyProperty; +import utils.autoSuggestion.AutoSuggestionsTextField; +import utils.autoSuggestion.strategies.SuggestionStrategyMoment; import utils.dragAndDrop.DragStore; import utils.modelControllers.ListView.ListViewController; import utils.modelControllers.ListView.ListViewUpdate; -import utils.popups.TextEntryController; import java.io.IOException; import java.net.URL; @@ -35,6 +35,8 @@ public class ConcretePropertyController extends ListViewController { - TextEntryController c = TextEntryController.enterText( - property.getName(), - property.getValue(), - 20, - new SuggestionStrategyProperty() - ); - //c.setStrategy(); - if(c.getState() == DialogState.SUCCESS){ - EditConcretePropertyValue cmd = new EditConcretePropertyValue(property, c.getValue()); - String oldValue = property.getValue(); - String newValue = c.getValue(); - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterExecute, () -> { modelisationSpaceHookNotifier.notifyConcretePropertyValueChanged(oldValue, property); }); - cmd.hooks().setHook(ModelUserActionCommandHooks.HookMoment.AfterUndo, () -> { modelisationSpaceHookNotifier.notifyConcretePropertyValueChanged(newValue, property);}); - HistoryManager.addCommand(cmd, true); + if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) { + if (mouseEvent.getClickCount() == 2) { + passInRenamingMode(); + } } }); @@ -92,23 +86,17 @@ public void initialize(URL url, ResourceBundle resourceBundle) { private void setupDragAndDrop() { - container.setOnDragEntered(dragEvent -> { - container.setStyle("-fx-opacity: 1;"); - }); + container.setOnDragEntered(dragEvent -> container.setStyle("-fx-opacity: 1;")); container.setOnDragOver(dragEvent -> { container.setStyle("-fx-opacity: 1;"); if( !dragEvent.isAccepted() - && DragStore.getDraggable().getDataFormat() == Descripteme.format + && DragStore.getDraggable().getDataFormat() == Descripteme.format + && justificationController.acceptDescripteme(DragStore.getDraggable()) ){ - if(justificationController.acceptDescripteme(DragStore.getDraggable())){ - container.setStyle("-fx-opacity: 0.5;"); - dragEvent.acceptTransferModes(TransferMode.COPY_OR_MOVE); - } - else { - //dragEvent.acceptTransferModes(TransferMode.NONE); - } + container.setStyle("-fx-opacity: 0.5;"); + dragEvent.acceptTransferModes(TransferMode.COPY_OR_MOVE); } }); @@ -123,9 +111,7 @@ private void setupDragAndDrop() { } }); - container.setOnDragExited(dragEvent -> { - container.setStyle("-fx-opacity: 1;"); - }); + container.setOnDragExited(dragEvent -> container.setStyle("-fx-opacity: 1;")); } @Override @@ -146,4 +132,50 @@ public void onUpdate(ListViewUpdate update) { public void onUnmount() { } + + + public void passInRenamingMode() { + if (renamingMode) return; + renamingField = new AutoSuggestionsTextField(value.getText(), new SuggestionStrategyMoment()); + + renamingField.setAlignment(Pos.CENTER_LEFT); + renamingField.end(); + renamingField.selectAll(); + + int indexOfValue = this.head.getChildren().indexOf(value); + + renamingField.focusedProperty().addListener((obs, oldVal, newVal) -> { + if (!newVal){ //unfocus + exitRenamingMode(indexOfValue, false); + } + }); + + renamingField.setOnKeyPressed(keyEvent -> { + if(keyEvent.getCode() == KeyCode.ENTER) { + exitRenamingMode(indexOfValue, false); + } + + if(keyEvent.getCode() == KeyCode.ESCAPE) { + exitRenamingMode(indexOfValue, true); + } + }); + this.head.getChildren().remove(value); + this.head.getChildren().add(indexOfValue, renamingField); + renamingField.requestFocus(); + renamingMode = true; + } + + private void exitRenamingMode(int indexOfValue, boolean canceled) { + if (!renamingMode) return; + + if(!canceled && renamingField.getLength() > 0 && !value.getText().equals(renamingField.getText())) { + new EditConcretePropertyCommand(modelisationSpaceHookNotifier, property, renamingField.getText(), true).execute(); + } + + this.head.getChildren().remove(renamingField); + this.head.getChildren().add(indexOfValue, value); + renamingMode = false; + } + + } diff --git a/src/main/java/components/rootLayout/Controllers/RootLayoutController.java b/src/main/java/components/rootLayout/Controllers/RootLayoutController.java index 07d4887b..e9db274f 100644 --- a/src/main/java/components/rootLayout/Controllers/RootLayoutController.java +++ b/src/main/java/components/rootLayout/Controllers/RootLayoutController.java @@ -277,10 +277,8 @@ public void momentsComparaison(){ } @FXML - public void close(javafx.stage.WindowEvent event) { - System.out.println(event); - - appCommandFactory.closeApplication(event).execute(); + public void close() { + appCommandFactory.closeApplication().execute(); } @FXML diff --git a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java index 9d013c41..e864bb6a 100644 --- a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java +++ b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeCellController.java @@ -1,24 +1,27 @@ package components.schemaTree.Cell.Controllers; import application.configuration.Configuration; -import application.history.HistoryManager; -import components.schemaTree.Cell.appCommands.SchemaTreeCommandFactory; -import components.schemaTree.Cell.modelCommands.RenameSchemaTreePluggable; import components.schemaTree.Cell.SchemaTreePluggable; +import components.schemaTree.Cell.appCommands.SchemaTreeCommandFactory; import components.schemaTree.Section; import javafx.application.Platform; -import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.geometry.Pos; -import javafx.scene.control.*; +import javafx.scene.control.Label; +import javafx.scene.control.MenuButton; +import javafx.scene.control.MenuItem; import javafx.scene.image.ImageView; import javafx.scene.input.KeyCode; +import javafx.scene.input.TransferMode; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Pane; +import models.SchemaCategory; +import models.SchemaFolder; import utils.ResourceLoader; import utils.autoSuggestion.AutoSuggestionsTextField; import utils.autoSuggestion.strategies.SuggestionStrategy; +import utils.dragAndDrop.DragStore; import java.net.URL; import java.util.ResourceBundle; @@ -76,6 +79,8 @@ public void initialize(URL url, ResourceBundle resourceBundle) { if(element.mustBeRenamed()) passInRenamingMode(true); }); + + } diff --git a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeFolderController.java b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeFolderController.java index 0e9884b9..ebd8ccaf 100644 --- a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeFolderController.java +++ b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeFolderController.java @@ -5,6 +5,7 @@ import models.SchemaCategory; import models.SchemaFolder; import javafx.scene.control.MenuItem; +import components.toolbox.controllers.ToolBoxControllers; import utils.autoSuggestion.strategies.SuggestionStrategy; import utils.autoSuggestion.strategies.SuggestionStrategyFolder; @@ -48,6 +49,11 @@ public void initialize(URL url, ResourceBundle resourceBundle) { MenuItem deleteButton = new MenuItem(Configuration.langBundle.getString("delete")); deleteButton.setOnAction(actionEvent -> { cmdFactory.removeTreeElement(folder).execute(); + if (folder.momentTypesProperty() != null) { + folder.momentTypesProperty().forEach(momentType -> { + ToolBoxControllers.getToolBoxControllersInstance().removeMomentTypeCommand(momentType); + }); + } }); optionsMenu.getItems().add(deleteButton); } diff --git a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeMomentTypeController.java b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeMomentTypeController.java new file mode 100644 index 00000000..68d7a378 --- /dev/null +++ b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeMomentTypeController.java @@ -0,0 +1,119 @@ +package components.schemaTree.Cell.Controllers; + +import application.configuration.Configuration; +import components.schemaTree.Cell.appCommands.SchemaTreeCommandFactory; +import components.toolbox.controllers.ToolBoxControllers; +import javafx.geometry.Pos; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Tooltip; +import javafx.scene.input.KeyCode; +import javafx.util.Duration; +import models.SchemaCategory; +import models.SchemaMomentType; +import models.SchemaProperty; +import utils.autoSuggestion.AutoSuggestionsTextField; +import utils.autoSuggestion.strategies.SuggestionStrategy; +import utils.autoSuggestion.strategies.SuggestionStrategyMoment; + +import java.net.URL; +import java.util.ResourceBundle; + +public class SchemaTreeMomentTypeController extends SchemaTreeCellController { + + private SchemaMomentType schemaMomentType; + private SchemaTreeCommandFactory cmdFactory; + private boolean renamingMode = false; + + public SchemaTreeMomentTypeController(SchemaMomentType schemaMomentType, SchemaTreeCommandFactory cmdFactory) { + super(schemaMomentType, cmdFactory); + this.schemaMomentType = schemaMomentType; + this.cmdFactory = cmdFactory; + } + + @Override + protected SuggestionStrategy getSuggestionStrategy() { + return new SuggestionStrategyMoment(); + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + super.initialize(url, resourceBundle); + name.textProperty().bind(this.schemaMomentType.nameProperty()); + + MenuItem deleteButton = new MenuItem(Configuration.langBundle.getString("delete")); + deleteButton.setOnAction(actionEvent -> { + cmdFactory.removeTreeElement(schemaMomentType).execute(); + ToolBoxControllers.getToolBoxControllersInstance().removeMomentTypeCommand(schemaMomentType); + }); + optionsMenu.getItems().add(deleteButton); + + MenuItem showButton = new MenuItem(); + if (ToolBoxControllers.getToolBoxControllersInstance().getCurrentMomentTypeControllers().contains(this.schemaMomentType.getMomentTypeController())) { + showButton.setText(Configuration.langBundle.getString("hide_in_toolbox")); + } + else { + showButton.setText(Configuration.langBundle.getString("show_in_toolbox")); + } + + showButton.setOnAction(actionEvent -> { + if (ToolBoxControllers.getToolBoxControllersInstance().getCurrentMomentTypeControllers().contains(this.schemaMomentType.getMomentTypeController())) { + ToolBoxControllers.getToolBoxControllersInstance().hide(schemaMomentType.getMomentTypeController()); + showButton.textProperty().set(Configuration.langBundle.getString("show_in_toolbox")); + } else { + ToolBoxControllers.getToolBoxControllersInstance().show(schemaMomentType.getMomentTypeController()); + showButton.textProperty().set(Configuration.langBundle.getString("hide_in_toolbox")); + } + }); + optionsMenu.getItems().add(showButton); + } + + @Override + public void setOnHover(boolean YoN) { + super.setOnHover(YoN); + + StringBuilder message = new StringBuilder(schemaMomentType.getName() + "\n"); + for (SchemaCategory sc : schemaMomentType.categoriesProperty()) { + message.append('\n').append(sc.getName()).append(" :\n"); + for (SchemaProperty sp : sc.propertiesProperty()) { + message.append("\t- ").append(sp.getName()).append("\n"); + } + } + + Tooltip tt = new Tooltip(message.toString()); + tt.setShowDelay(Duration.millis(500)); + Tooltip.install(nameDisplayer, tt); + } + + @Override + public void passInRenamingMode(boolean YoN) { + if (YoN != renamingMode) { + if (YoN) { + renamingField = new AutoSuggestionsTextField(name.getText(), new SuggestionStrategyMoment()); + renamingField.setAlignment(Pos.CENTER); + renamingField.end(); + renamingField.selectAll(); + + renamingField.focusedProperty().addListener((obs, oldVal, newVal) -> { + if (!newVal) + passInRenamingMode(false); + }); + + renamingField.setOnKeyPressed(keyEvent -> { + if (keyEvent.getCode() == KeyCode.ENTER) { + if (renamingField.getLength() > 0) { + cmdFactory.renameTreeSchemaMomentTypes(this.schemaMomentType, renamingField.getText()).execute(); + } + passInRenamingMode(false); + } + }); + + this.nameDisplayer.setLeft(renamingField); + renamingField.requestFocus(); + renamingMode = true; + } else { + this.nameDisplayer.setLeft(name); + renamingMode = false; + } + } + } +} diff --git a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeRootController.java b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeRootController.java index bc39486f..62721e50 100644 --- a/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeRootController.java +++ b/src/main/java/components/schemaTree/Cell/Controllers/SchemaTreeRootController.java @@ -2,6 +2,7 @@ import application.configuration.Configuration; import components.schemaTree.Cell.appCommands.SchemaTreeCommandFactory; +import models.SchemaCategory; import models.SchemaFolder; import models.SchemaTreeRoot; import javafx.scene.control.MenuItem; @@ -42,8 +43,16 @@ public void initialize(URL url, ResourceBundle resourceBundle) { SchemaFolder f = new SchemaFolder(Configuration.langBundle.getString("folder")); cmdFactory.addSchemaTreeChild(f).execute(); }); - optionsMenu.getItems().add(addFolderButton); + + MenuItem addCategoryButton = new MenuItem(Configuration.langBundle.getString("add_category")); + addCategoryButton.setOnAction(actionEvent -> { + SchemaCategory newModel = new SchemaCategory("category"); + cmdFactory.addSchemaTreeChild(newModel).execute(); + }); + optionsMenu.getItems().add(addCategoryButton); + + optionsMenu.setVisible(false); } } diff --git a/src/main/java/components/schemaTree/Cell/SchemaTreeCell.java b/src/main/java/components/schemaTree/Cell/SchemaTreeCell.java index b89ac0cb..87a87879 100644 --- a/src/main/java/components/schemaTree/Cell/SchemaTreeCell.java +++ b/src/main/java/components/schemaTree/Cell/SchemaTreeCell.java @@ -5,10 +5,9 @@ import components.schemaTree.Cell.modelCommands.MoveSchemaTreePluggable; import components.schemaTree.Cell.Controllers.SchemaTreeCellController; import components.schemaTree.Section; +import components.toolbox.controllers.ToolBoxControllers; import javafx.scene.control.TreeItem; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; +import models.*; import utils.reactiveTree.LeafToRootIterator; import components.schemaTree.Cell.Visitors.CreateControllerVisitor; import javafx.event.EventHandler; @@ -101,10 +100,22 @@ public void handle(DragEvent event) { selfCell.setOnDragOver(new EventHandler() { public void handle(DragEvent event) { + if (DragStore.getDraggable().getDataFormat() == Moment.format) { + Moment m = DragStore.getDraggable(); + + if (ToolBoxControllers.getToolBoxControllersInstance().canBeDragged(m)) { + event.acceptTransferModes(TransferMode.MOVE); + } else { + event.acceptTransferModes(TransferMode.NONE); + } + event.consume(); + return; + + } + boolean accept = false; - // TODO: get size of the target Section sect = controller.mouseIsDraggingOn(event.getY()); - SchemaTreePluggable source = DragStore.getDraggable(); + SchemaTreePluggable source = DragStore.getDraggable(); SchemaTreePluggable target = selfCell.getItem(); SchemaTreePluggable sourceParent = ((SchemaTreeCell)(event.getGestureSource())).getTreeItem() @@ -113,7 +124,7 @@ public void handle(DragEvent event) { if (!isAncestor(source, selfCell) && source != target && !isDirectParent(source, selfCell)) { if (sect == Section.middle) { - if (target.canContain(source) && !target.hasChild(source) && source.canChangeParent()) { + if (target.canContain(source) && !target.hasChild(source) && source.canChangeParent()) { selfCell.setStyle("-fx-background-color: #999;-fx-font-weight: bold;"); controller.setStyle(""); accept = true; @@ -146,56 +157,60 @@ else if (sect == Section.top) { selfCell.setOnDragDropped(new EventHandler() { public void handle(DragEvent event) { - - //Checking if we are in the case of an internal drag and drop (between TreeElementModels) - if(SchemaTreeCell.checkInternalDrop(event.getDragboard())) { - - SchemaTreePluggable source = DragStore.getDraggable(); - DragStore.clearStore(); - SchemaTreePluggable target = selfCell.getItem(); - - Section sect = controller.mouseIsDraggingOn(event.getY()); - - SchemaTreePluggable sourceParent = ((SchemaTreeCell)(event.getGestureSource())).getTreeItem() - .getParent().getValue(); - SchemaTreePluggable parentTarget = selfCell.getTreeItem().getParent().getValue(); - - SchemaTreePluggable newParent = null; - - int newIndex = -1; - - if (sect != Section.middle) { - newParent = parentTarget; - int oldIndex = sourceParent.getChildIndex(source); - newIndex = parentTarget.getChildIndex(target); - - if (sourceParent == parentTarget) { - if (sect == Section.top && oldIndex < newIndex) { - newIndex--; + if (DragStore.getDraggable().getDataFormat() == Moment.format) { + Moment m = DragStore.getDraggable(); + ToolBoxControllers.getToolBoxControllersInstance().addMomentTypeCommand(m); + } else { + //Checking if we are in the case of an internal drag and drop (between TreeElementModels) + if(SchemaTreeCell.checkInternalDrop(event.getDragboard())) { + + SchemaTreePluggable source = DragStore.getDraggable(); + DragStore.clearStore(); + SchemaTreePluggable target = selfCell.getItem(); + + Section sect = controller.mouseIsDraggingOn(event.getY()); + + SchemaTreePluggable sourceParent = ((SchemaTreeCell)(event.getGestureSource())).getTreeItem() + .getParent().getValue(); + SchemaTreePluggable parentTarget = selfCell.getTreeItem().getParent().getValue(); + + SchemaTreePluggable newParent = null; + + int newIndex = -1; + + if (sect != Section.middle) { + newParent = parentTarget; + int oldIndex = sourceParent.getChildIndex(source); + newIndex = parentTarget.getChildIndex(target); + + if (sourceParent == parentTarget) { + if (sect == Section.top && oldIndex < newIndex) { + newIndex--; + } + else if (sect == Section.bottom && oldIndex > newIndex) { + newIndex++; + } } - else if (sect == Section.bottom && oldIndex > newIndex) { - newIndex++; + else { + if (sect == Section.bottom) { + newIndex++; + } } + selfCell.getTreeView().getSelectionModel().select(selfCell.getTreeView().getSelectionModel() + .getSelectedItem()); // TODO: fix } else { - if (sect == Section.bottom) { - newIndex++; - } + // sect == middle so change parent + newParent = target; + selfCell.getTreeView().getSelectionModel().select(selfCell.getTreeItem()); } - selfCell.getTreeView().getSelectionModel().select(selfCell.getTreeView().getSelectionModel() - .getSelectedItem()); // TODO: fix - } - else { - // sect == middle so change parent - newParent = target; - selfCell.getTreeView().getSelectionModel().select(selfCell.getTreeItem()); - } - HistoryManager.addCommand(new MoveSchemaTreePluggable(sourceParent, newParent, source, newIndex), - true); + HistoryManager.addCommand(new MoveSchemaTreePluggable(sourceParent, newParent, source, newIndex), + true); + } + event.setDropCompleted(false); + event.consume(); } - event.setDropCompleted(false); - event.consume(); } }); @@ -217,7 +232,8 @@ private static boolean checkInternalDrop(Dragboard db) { return ( db.hasContent(SchemaCategory.format) || db.hasContent(SchemaFolder.format) || - db.hasContent(SchemaProperty.format) + db.hasContent(SchemaProperty.format) || + db.hasContent(SchemaMomentType.format) ); } diff --git a/src/main/java/components/schemaTree/Cell/Utils.java b/src/main/java/components/schemaTree/Cell/Utils.java index f76b7e29..0190e616 100644 --- a/src/main/java/components/schemaTree/Cell/Utils.java +++ b/src/main/java/components/schemaTree/Cell/Utils.java @@ -1,5 +1,6 @@ package components.schemaTree.Cell; +import models.SchemaMomentType; import javafx.scene.control.TreeItem; import models.SchemaCategory; import models.SchemaFolder; @@ -24,6 +25,10 @@ public static boolean IsSchemaTreeProperty(SchemaTreePluggable item){ return item.getDataFormat() == SchemaProperty.format; } + public static boolean IsSchemaTreeMomentType(SchemaTreePluggable item){ + return item.getDataFormat() == SchemaMomentType.format; + } + public static boolean IsSameType(SchemaTreePluggable a, SchemaTreePluggable b) { return a.getDataFormat() == b.getDataFormat(); } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyDeletedVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyDeletedVisitor.java index 5acd526a..3f990fb0 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyDeletedVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyDeletedVisitor.java @@ -1,9 +1,7 @@ package components.schemaTree.Cell.Visitors; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; public class CanTreeElementBeSafelyDeletedVisitor extends SchemaTreePluggableVisitor { @@ -32,5 +30,10 @@ public void visit(SchemaProperty element) { result = false; } + @Override + public void visit(SchemaMomentType element) { + result = true; + } + public boolean elementCanBeSafelyDeleted() { return result; } } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyRenamedVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyRenamedVisitor.java index 12a14a60..7493256e 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyRenamedVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CanTreeElementBeSafelyRenamedVisitor.java @@ -1,9 +1,7 @@ package components.schemaTree.Cell.Visitors; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; public class CanTreeElementBeSafelyRenamedVisitor extends SchemaTreePluggableVisitor { @@ -27,5 +25,10 @@ public void visit(SchemaProperty element) { result = false; } + @Override + public void visit(SchemaMomentType element) { + result = true; + } + public boolean elementCanBeSafelyRenamed() { return result; } } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CreateAddChildStrategyVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CreateAddChildStrategyVisitor.java index a2c7177e..db864d08 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CreateAddChildStrategyVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CreateAddChildStrategyVisitor.java @@ -1,9 +1,7 @@ package components.schemaTree.Cell.Visitors; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; import components.schemaTree.Cell.SchemaTreePluggable; import components.schemaTree.Cell.appCommands.strategies.ContainerCreateChildStrategy; import components.schemaTree.Cell.appCommands.strategies.LeafCreateChildStrategy; @@ -44,5 +42,10 @@ public void visit(SchemaProperty element) { result = new LeafCreateChildStrategy(); } + @Override + public void visit(SchemaMomentType element) { + result = new LeafCreateChildStrategy(); + } + public AddChildStrategy getResultStrategy() { return result; } } \ No newline at end of file diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CreateControllerVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CreateControllerVisitor.java index a28a8cf0..f2e44d7b 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CreateControllerVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CreateControllerVisitor.java @@ -1,10 +1,8 @@ package components.schemaTree.Cell.Visitors; import components.schemaTree.Cell.Controllers.*; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; import components.schemaTree.Cell.appCommands.SchemaTreeCommandFactory; public class CreateControllerVisitor extends SchemaTreePluggableVisitor { @@ -34,6 +32,11 @@ public void visit(SchemaProperty element) { resultController = new SchemaTreePropertyController(element, cmdFactory); } + @Override + public void visit(SchemaMomentType element) { + resultController = new SchemaTreeMomentTypeController(element, cmdFactory); + } + public SchemaTreeCellController getResultController() { return resultController; } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CreateRemovingStrategyVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CreateRemovingStrategyVisitor.java index 64c1fbfc..54b09343 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CreateRemovingStrategyVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CreateRemovingStrategyVisitor.java @@ -1,9 +1,7 @@ package components.schemaTree.Cell.Visitors; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; import components.schemaTree.Cell.SchemaTreePluggable; import components.schemaTree.Cell.appCommands.RemovingStrategy; import components.schemaTree.Cell.appCommands.strategies.RemovableRemovingStrategy; @@ -45,6 +43,11 @@ public void visit(SchemaProperty element) { result = new RemovableRemovingStrategy<>(view, parent, item); } + @Override + public void visit(SchemaMomentType element) { + result = new RemovableRemovingStrategy<>(view, parent, item); + } + public RemovingStrategy getResultStrategy() { return result; } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/CreateSchemaTreeItemVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/CreateSchemaTreeItemVisitor.java index e66e8fb8..5de3c9d1 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/CreateSchemaTreeItemVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/CreateSchemaTreeItemVisitor.java @@ -3,10 +3,8 @@ import components.schemaTree.Cell.SchemaTreeContainer; import components.schemaTree.Cell.SchemaTreePluggable; import components.schemaTree.Section; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; import utils.reactiveTree.ReactiveTreeElement; public class CreateSchemaTreeItemVisitor extends SchemaTreePluggableVisitor { @@ -16,15 +14,13 @@ public class CreateSchemaTreeItemVisitor extends SchemaTreePluggableVisitor { @Override public void visit(SchemaTreeRoot element) { SchemaTreeContainer item = new SchemaTreeContainer(element); - item.bindChildrenCollection(element.foldersProperty()); + item.bindChildrenCollection(element.childrenProperty()); result = item; } @Override public void visit(SchemaFolder element) { SchemaTreeContainer item = new SchemaTreeContainer(element); - /*item.bindChildrenCollection(element.foldersProperty()); - item.bindChildrenCollection(element.categoriesProperty());*/ item.bindChildrenCollection(element.childrenProperty()); result = item; } @@ -41,6 +37,11 @@ public void visit(SchemaProperty element) { result = new ReactiveTreeElement(element); } + @Override + public void visit(SchemaMomentType element) { + result = new ReactiveTreeElement(element); + } + public ReactiveTreeElement getSchemaTreeItem() { return result; } diff --git a/src/main/java/components/schemaTree/Cell/Visitors/SchemaTreePluggableVisitor.java b/src/main/java/components/schemaTree/Cell/Visitors/SchemaTreePluggableVisitor.java index afcc6f1b..27c4d1ef 100644 --- a/src/main/java/components/schemaTree/Cell/Visitors/SchemaTreePluggableVisitor.java +++ b/src/main/java/components/schemaTree/Cell/Visitors/SchemaTreePluggableVisitor.java @@ -1,9 +1,7 @@ package components.schemaTree.Cell.Visitors; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; public abstract class SchemaTreePluggableVisitor { @@ -11,5 +9,6 @@ public abstract class SchemaTreePluggableVisitor { public abstract void visit(SchemaFolder element); public abstract void visit(SchemaCategory element); public abstract void visit(SchemaProperty element); + public abstract void visit(SchemaMomentType element); } diff --git a/src/main/java/components/schemaTree/Cell/appCommands/ChangeColorCategoryCommand.java b/src/main/java/components/schemaTree/Cell/appCommands/ChangeColorCategoryCommand.java index 45420151..3e304982 100644 --- a/src/main/java/components/schemaTree/Cell/appCommands/ChangeColorCategoryCommand.java +++ b/src/main/java/components/schemaTree/Cell/appCommands/ChangeColorCategoryCommand.java @@ -1,17 +1,9 @@ package components.schemaTree.Cell.appCommands; -import application.configuration.Configuration; import application.history.HistoryManager; -import components.modelisationSpace.moment.modelCommands.ChangeColorMoment; -import components.modelisationSpace.moment.modelCommands.RenameMoment; import components.schemaTree.Cell.modelCommands.ChangeColorTreePluggable; -import models.Moment; import models.SchemaCategory; -import utils.DialogState; -import utils.autoSuggestion.strategies.SuggestionStrategyMoment; import utils.command.Executable; -import utils.popups.TextEntryController; -import utils.popups.WarningPopup; public class ChangeColorCategoryCommand implements Executable { diff --git a/src/main/java/components/schemaTree/Cell/appCommands/SchemaTreeCommandFactory.java b/src/main/java/components/schemaTree/Cell/appCommands/SchemaTreeCommandFactory.java index ada02190..3feb175b 100644 --- a/src/main/java/components/schemaTree/Cell/appCommands/SchemaTreeCommandFactory.java +++ b/src/main/java/components/schemaTree/Cell/appCommands/SchemaTreeCommandFactory.java @@ -9,11 +9,13 @@ import components.schemaTree.Cell.Visitors.CreateRemovingStrategyVisitor; import components.schemaTree.Cell.appCommands.strategies.UnremovableRemovingStrategy; import components.schemaTree.Cell.modelCommands.RenameSchemaTreePluggable; +import components.toolbox.appCommand.RenameMomentTypesCommand; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import models.SchemaCategory; +import models.SchemaMomentType; import utils.removable.IRemovable; public class SchemaTreeCommandFactory { @@ -43,6 +45,7 @@ public RemovingStrategy removeTreeEle } else { Alert alert = new Alert(Alert.AlertType.CONFIRMATION, Configuration.langBundle.getString("schemaTree_deletion_prevent"), ButtonType.YES, ButtonType.NO); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); if (alert.getResult() == ButtonType.YES) { return v.getResultStrategy(); @@ -64,6 +67,7 @@ public void renameTreeElement(E element, String } else { Alert alert = new Alert(Alert.AlertType.CONFIRMATION, Configuration.langBundle.getString("schemaTree_renaming_prevent"), ButtonType.YES, ButtonType.NO); + alert.getDialogPane().getStylesheets().add(getClass().getResource("/css/application.css").toExternalForm()); alert.showAndWait(); if (alert.getResult() == ButtonType.YES) { HistoryManager.addCommand(cmd, !element.mustBeRenamed()); @@ -71,6 +75,10 @@ public void renameTreeElement(E element, String } } + public RenameMomentTypesCommand renameTreeSchemaMomentTypes(SchemaMomentType element, String newName) { + return new RenameMomentTypesCommand(element, newName); + } + public ChangeColorCategoryCommand colorCommand(SchemaCategory c, String newColor) { return new ChangeColorCategoryCommand(c, newColor); } diff --git a/src/main/java/components/schemaTree/Cell/modelCommands/RenameSchemaMomentTypes.java b/src/main/java/components/schemaTree/Cell/modelCommands/RenameSchemaMomentTypes.java new file mode 100644 index 00000000..6c4c3324 --- /dev/null +++ b/src/main/java/components/schemaTree/Cell/modelCommands/RenameSchemaMomentTypes.java @@ -0,0 +1,28 @@ +package components.schemaTree.Cell.modelCommands; + +import application.history.ModelUserActionCommand; +import models.SchemaMomentType; + +public class RenameSchemaMomentTypes extends ModelUserActionCommand { + SchemaMomentType element; + String newName; + String originalName; + + public RenameSchemaMomentTypes(SchemaMomentType element, String newName) { + this.element = element; + this.newName = newName; + this.originalName = element.getName(); + } + + @Override + public Void execute() { + element.setName(newName); + return null; + } + + @Override + public Void undo() { + element.setName(originalName); + return null; + } +} diff --git a/src/main/java/components/schemaTree/Controllers/SchemaTreeController.java b/src/main/java/components/schemaTree/Controllers/SchemaTreeController.java index 1d2dfa46..30dfd74c 100644 --- a/src/main/java/components/schemaTree/Controllers/SchemaTreeController.java +++ b/src/main/java/components/schemaTree/Controllers/SchemaTreeController.java @@ -1,18 +1,18 @@ package components.schemaTree.Controllers; +import application.configuration.Configuration; +import components.schemaTree.Cell.SchemaTreeCell; import components.schemaTree.Cell.SchemaTreePluggable; -import models.SchemaTreeRoot; import components.schemaTree.Cell.Visitors.CreateSchemaTreeItemVisitor; -import components.schemaTree.Cell.SchemaTreeCell; -import application.configuration.Configuration; import components.schemaTree.Section; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.control.TreeView; -import utils.GlobalVariables; import javafx.scene.layout.Pane; +import models.SchemaTreeRoot; +import utils.GlobalVariables; import java.io.IOException; import java.net.URL; diff --git a/src/main/java/components/schemaTree/Services/categoryUsesCounter/ResetCategoryUsesCounterVisitor.java b/src/main/java/components/schemaTree/Services/categoryUsesCounter/ResetCategoryUsesCounterVisitor.java index 2bb6cd39..ce66e185 100644 --- a/src/main/java/components/schemaTree/Services/categoryUsesCounter/ResetCategoryUsesCounterVisitor.java +++ b/src/main/java/components/schemaTree/Services/categoryUsesCounter/ResetCategoryUsesCounterVisitor.java @@ -1,16 +1,14 @@ package components.schemaTree.Services.categoryUsesCounter; import components.schemaTree.Cell.Visitors.SchemaTreePluggableVisitor; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; public class ResetCategoryUsesCounterVisitor extends SchemaTreePluggableVisitor { @Override public void visit(SchemaTreeRoot element) { - element.foldersProperty().forEach(schemaFolder -> { schemaFolder.accept(this); }); + element.childrenProperty().forEach(schemaFolder -> { schemaFolder.accept(this); }); } @Override @@ -29,4 +27,9 @@ public void visit(SchemaProperty element) { } + @Override + public void visit(SchemaMomentType element) { + + } + } diff --git a/src/main/java/components/schemaTree/Services/propertyUsesCounter/ResetPropertyUsesCounterVisitor.java b/src/main/java/components/schemaTree/Services/propertyUsesCounter/ResetPropertyUsesCounterVisitor.java index 47fb794d..4968470f 100644 --- a/src/main/java/components/schemaTree/Services/propertyUsesCounter/ResetPropertyUsesCounterVisitor.java +++ b/src/main/java/components/schemaTree/Services/propertyUsesCounter/ResetPropertyUsesCounterVisitor.java @@ -1,16 +1,14 @@ package components.schemaTree.Services.propertyUsesCounter; import components.schemaTree.Cell.Visitors.SchemaTreePluggableVisitor; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaProperty; -import models.SchemaTreeRoot; +import models.SchemaMomentType; +import models.*; public class ResetPropertyUsesCounterVisitor extends SchemaTreePluggableVisitor { @Override public void visit(SchemaTreeRoot element) { - element.foldersProperty().forEach(schemaFolder -> { schemaFolder.accept(this); }); + element.childrenProperty().forEach(schemaFolder -> { schemaFolder.accept(this); }); } @Override @@ -29,4 +27,9 @@ public void visit(SchemaProperty element) { element.setNumberOfUsesInModelisation(0); } + @Override + public void visit(SchemaMomentType element) { + element.setNumberOfUsesInModelisation(0); + } + } diff --git a/src/main/java/components/toolbox/appCommand/AddSchemaMomentTypeCommand.java b/src/main/java/components/toolbox/appCommand/AddSchemaMomentTypeCommand.java new file mode 100644 index 00000000..613c1f47 --- /dev/null +++ b/src/main/java/components/toolbox/appCommand/AddSchemaMomentTypeCommand.java @@ -0,0 +1,23 @@ +package components.toolbox.appCommand; + +import application.history.HistoryManager; +import components.toolbox.controllers.ToolBoxControllers; +import components.toolbox.history.commands.AddSchemaMomentType; +import models.SchemaMomentType; +import utils.command.Executable; + +public class AddSchemaMomentTypeCommand implements Executable { + ToolBoxControllers toolBoxControllers; + SchemaMomentType schemaMomentType; + + public AddSchemaMomentTypeCommand(ToolBoxControllers tbc, SchemaMomentType smt) { + this.toolBoxControllers = tbc; + this.schemaMomentType = smt; + } + + @Override + public Object execute() { + HistoryManager.addCommand(new AddSchemaMomentType(this.toolBoxControllers, this.schemaMomentType), true); + return null; + } +} diff --git a/src/main/java/components/toolbox/appCommand/RemoveSchemaMomentTypeCommand.java b/src/main/java/components/toolbox/appCommand/RemoveSchemaMomentTypeCommand.java new file mode 100644 index 00000000..24e4b10a --- /dev/null +++ b/src/main/java/components/toolbox/appCommand/RemoveSchemaMomentTypeCommand.java @@ -0,0 +1,23 @@ +package components.toolbox.appCommand; + +import application.history.HistoryManager; +import components.toolbox.controllers.ToolBoxControllers; +import components.toolbox.history.commands.RemoveSchemaMomentType; +import models.SchemaMomentType; +import utils.command.Executable; + +public class RemoveSchemaMomentTypeCommand implements Executable { + ToolBoxControllers toolBoxControllers; + SchemaMomentType schemaMomentType; + + public RemoveSchemaMomentTypeCommand(ToolBoxControllers tbc, SchemaMomentType smt) { + this.toolBoxControllers = tbc; + this.schemaMomentType = smt; + } + + @Override + public Object execute() { + HistoryManager.addCommand(new RemoveSchemaMomentType(this.toolBoxControllers, this.schemaMomentType), true); + return null; + } +} \ No newline at end of file diff --git a/src/main/java/components/toolbox/appCommand/RenameMomentTypesCommand.java b/src/main/java/components/toolbox/appCommand/RenameMomentTypesCommand.java new file mode 100644 index 00000000..95d22607 --- /dev/null +++ b/src/main/java/components/toolbox/appCommand/RenameMomentTypesCommand.java @@ -0,0 +1,25 @@ +package components.toolbox.appCommand; + +import application.history.HistoryManager; +import components.schemaTree.Cell.modelCommands.RenameSchemaMomentTypes; +import models.SchemaMomentType; +import utils.command.Executable; + +public class RenameMomentTypesCommand implements Executable { + + private SchemaMomentType element; + private String newName; + + public RenameMomentTypesCommand(SchemaMomentType element, String newName) { + this.element = element; + this.newName = newName; + } + + @Override + public Object execute() { + RenameSchemaMomentTypes rsmt = new RenameSchemaMomentTypes(element, newName); + HistoryManager.addCommand(rsmt, true); + + return null; + } +} diff --git a/src/main/java/components/toolbox/controllers/MomentTypeController.java b/src/main/java/components/toolbox/controllers/MomentTypeController.java new file mode 100644 index 00000000..f7a6fab9 --- /dev/null +++ b/src/main/java/components/toolbox/controllers/MomentTypeController.java @@ -0,0 +1,138 @@ +package components.toolbox.controllers; + +import application.configuration.Configuration; +import components.toolbox.appCommand.RenameMomentTypesCommand; +import javafx.util.Duration; +import models.SchemaMomentType; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.input.*; +import javafx.scene.layout.BorderPane; +import models.Moment; +import models.*; +import utils.autoSuggestion.AutoSuggestionsTextField; +import utils.autoSuggestion.strategies.SuggestionStrategyMoment; +import utils.dragAndDrop.DragStore; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +public class MomentTypeController implements Initializable { + private @FXML BorderPane momentTypeBorderPane; + private @FXML Label momentTypeLabel; + private SchemaMomentType schemaMomentType; + + private boolean renamingMode = false; + private AutoSuggestionsTextField renamingField; + + public MomentTypeController(Moment moment) { + this.schemaMomentType = new SchemaMomentType(moment, this); + } + + public MomentTypeController(SchemaMomentType schemaMomentType) { + this.schemaMomentType = schemaMomentType; + } + + public static Node createMomentTypeController(MomentTypeController controller) { + try { + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(controller.getClass().getResource("/views/Toolbox/components/MomentType.fxml")); + loader.setController(controller); + loader.setResources(Configuration.langBundle); + return loader.load(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + this.momentTypeLabel.textProperty().bind(this.schemaMomentType.nameProperty()); + this.momentTypeBorderPane.setStyle("-fx-background-color: #"+this.schemaMomentType.getColor()+";"); + setupDragAndDrop(); + updatePopUp(); + + this.momentTypeBorderPane.setOnMouseClicked(mouseEvent -> { + if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) { + if (mouseEvent.getClickCount() == 2) { + passInRenamingMode(true); + } + } + }); + + schemaMomentType.nameProperty().addListener((observableValue, o, t1) -> updatePopUp()); + schemaMomentType.categoriesProperty().addListener((observableValue, o, t1) -> updatePopUp()); + } + + private void setupDragAndDrop() { + momentTypeBorderPane.setOnDragDetected(event -> { + Dragboard db = momentTypeBorderPane.startDragAndDrop(TransferMode.MOVE); + ClipboardContent content = new ClipboardContent(); + content.put(SchemaMomentType.format, 0); + DragStore.setDraggable(schemaMomentType); + db.setContent(content); + event.consume(); + }); + } + + private void updatePopUp() { + StringBuilder message = new StringBuilder(schemaMomentType.getName() + "\n"); + for (SchemaCategory sc : schemaMomentType.categoriesProperty()) { + message.append('\n').append(sc.getName()).append(" :\n"); + for (SchemaProperty sp : sc.propertiesProperty()) { + message.append("\t- ").append(sp.getName()).append("\n"); + } + } + + Tooltip tt = new Tooltip(message.toString()); + tt.setShowDelay(Duration.millis(500)); + Tooltip.install(momentTypeBorderPane, tt); + } + + public boolean exists(Moment moment) { + return moment.getName().equals(this.schemaMomentType.getName()); + } + + public SchemaMomentType getSchemaMomentType() { + return schemaMomentType; + } + + public void passInRenamingMode(boolean YoN) { + if (YoN != renamingMode) { + if (YoN) { + renamingField = new AutoSuggestionsTextField(schemaMomentType.getName(), new SuggestionStrategyMoment()); + renamingField.setAlignment(Pos.BASELINE_CENTER); + renamingField.end(); + renamingField.selectAll(); + + renamingField.focusedProperty().addListener((obs, oldVal, newVal) -> { + if (!newVal) + passInRenamingMode(false); + }); + + renamingField.setOnKeyPressed(keyEvent -> { + if (keyEvent.getCode() == KeyCode.ENTER) { + if (renamingField.getLength() > 0) { + new RenameMomentTypesCommand(this.schemaMomentType, renamingField.getText()).execute(); + } + passInRenamingMode(false); + } + }); + + this.momentTypeBorderPane.setCenter(renamingField); + renamingField.requestFocus(); + renamingMode = true; + } else { + this.momentTypeBorderPane.setCenter(momentTypeLabel); + renamingMode = false; + } + } + } +} diff --git a/src/main/java/components/toolbox/controllers/ToolBoxControllers.java b/src/main/java/components/toolbox/controllers/ToolBoxControllers.java new file mode 100644 index 00000000..b944031e --- /dev/null +++ b/src/main/java/components/toolbox/controllers/ToolBoxControllers.java @@ -0,0 +1,182 @@ +package components.toolbox.controllers; + +import application.configuration.Configuration; +import components.templateSpace.controllers.TemplateSpaceController; +import components.toolbox.appCommand.AddSchemaMomentTypeCommand; +import components.toolbox.appCommand.RemoveSchemaMomentTypeCommand; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.input.TransferMode; +import javafx.scene.layout.HBox; +import models.*; +import utils.dragAndDrop.DragStore; + +import java.io.IOException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.ResourceBundle; + + +public class ToolBoxControllers extends HBox implements Initializable { + private @FXML HBox bodyToolBox; + private @FXML Button addMomentTypeFolder; + private @FXML HBox containerMomentsTypes; + private @FXML TemplateSpaceController templateSpaceController; + + public Project project; + private SchemaTreeRoot schemaTreeRoot; + private List currentMomentTypeControllers; + public static ToolBoxControllers instance; + + public static ToolBoxControllers getToolBoxControllersInstance(Project project) { + if (instance == null) { + instance = new ToolBoxControllers(); + instance.project = project; + instance.schemaTreeRoot = project.getSchemaTreeRoot(); + instance.currentMomentTypeControllers = new LinkedList<>(); + } + + if (!instance.project.equals(project)) { + instance.project = project; + instance.schemaTreeRoot = project.getSchemaTreeRoot(); + instance.currentMomentTypeControllers = new LinkedList<>(); + } + + for (MomentTypeController mtc : instance.project.getMomentTypeControllers()) { + // lINKAGE + mtc.getSchemaMomentType().setMomentTypeController(mtc); + if (!instance.currentMomentTypeControllers.contains(mtc)) { + instance.currentMomentTypeControllers.add(mtc); + } + } + + return instance; + } + + public static ToolBoxControllers getToolBoxControllersInstance() { + return instance; + } + + public Node createToolBoxControllers(ToolBoxControllers controller) { + try { + FXMLLoader fxmlLoader = new FXMLLoader(); + fxmlLoader.setLocation(controller.getClass().getResource("/views/Toolbox/Toolbox.fxml")); + fxmlLoader.setController(controller); + fxmlLoader.setResources(Configuration.langBundle); + + return fxmlLoader.load(); + } catch (IOException exception) { + throw new RuntimeException(exception); + } + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + updateGraphics(); + setupDragAndDrop(); + } + + private void updateGraphics() { + for (MomentTypeController mtc : instance.currentMomentTypeControllers) { + this.containerMomentsTypes.getChildren().add(MomentTypeController.createMomentTypeController(mtc)); + } + } + + private void setupDragAndDrop() { + /* On vérifie que l'on y glisse bien un moment */ + instance.containerMomentsTypes.setOnDragOver(dragEvent -> { + if (DragStore.getDraggable().getDataFormat() == Moment.format) { + if (canBeDragged(DragStore.getDraggable())) { + dragEvent.acceptTransferModes(TransferMode.MOVE); + instance.containerMomentsTypes.setStyle(" -fx-background-color: #bdc3c7;"); + dragEvent.consume(); + } + } + else { + dragEvent.acceptTransferModes(TransferMode.NONE); + } + }); + + /* Quand un élément est drag on l'ajoute au modèle + toolbox */ + instance.containerMomentsTypes.setOnDragDropped(dragEvent -> { + if (DragStore.getDraggable().getDataFormat() == Moment.format) { + Moment m = DragStore.getDraggable(); + if (canBeDragged(DragStore.getDraggable())) { + instance.addMomentTypeCommand(m); + } + } + dragEvent.setDropCompleted(true); + dragEvent.consume(); + }); + + /* Quand un draggable sort de draggableMomentsType */ + instance.containerMomentsTypes.setOnDragExited(dragEvent -> { + instance.containerMomentsTypes.setStyle(" -fx-background-color: none;"); + dragEvent.consume(); + }); + } + + // permet d'être utilisé dans l'arbre à gauche pour créer un type de moment + public void addMomentTypeCommand(Moment m) { + SchemaMomentType smt = new SchemaMomentType(m, new MomentTypeController(m)); + new AddSchemaMomentTypeCommand(instance, smt).execute(); + } + + public void removeMomentTypeCommand(SchemaMomentType smt) { + new RemoveSchemaMomentTypeCommand(instance, smt).execute(); + } + + // permet d'être utilisé dans l'arbre à gauche pour créer un type de moment + public boolean canBeDragged(Moment m) { + for (MomentTypeController momentTypeController : instance.currentMomentTypeControllers) { + if (momentTypeController.exists(m)) { + return false; + } + } + return true; + } + + public void addAMomentType(SchemaMomentType schemaMomentType) { + MomentTypeController momentTypeController = schemaMomentType.getMomentTypeController(); + instance.currentMomentTypeControllers.add(momentTypeController); + instance.containerMomentsTypes.getChildren().add(MomentTypeController.createMomentTypeController(momentTypeController)); + instance.schemaTreeRoot.addChild(momentTypeController.getSchemaMomentType()); + instance.project.getMomentTypeControllers().add(momentTypeController); + } + + public void removeAMomentType(SchemaMomentType schemaMomentType) { + // Remove only from Toolbox. To remove from SchemaTree use removeTreeElement + for(MomentTypeController momentTypeController : instance.project.getMomentTypeControllers()) { + if (momentTypeController.getSchemaMomentType().getName().equals(schemaMomentType.getName())) { + instance.schemaTreeRoot.removeChild(momentTypeController.getSchemaMomentType()); + instance.project.getMomentTypeControllers().remove(momentTypeController); + + if(instance.currentMomentTypeControllers.contains(momentTypeController)) { //si le momentType est affiché, on le supprime de la vue + instance.containerMomentsTypes.getChildren().remove(instance.currentMomentTypeControllers.indexOf(momentTypeController)); + instance.currentMomentTypeControllers.remove(momentTypeController); + } + break; + } + } + } + + public void hide(MomentTypeController mtc) { + this.containerMomentsTypes.getChildren().remove(instance.currentMomentTypeControllers.indexOf(mtc)); + this.currentMomentTypeControllers.remove(mtc); + } + + public void show(MomentTypeController mtc) { + this.containerMomentsTypes.getChildren().add(MomentTypeController.createMomentTypeController(mtc)); + this.currentMomentTypeControllers.add(mtc); + } + + public List getCurrentMomentTypeControllers() { + return currentMomentTypeControllers; + } + + +} diff --git a/src/main/java/components/toolbox/history/commands/AddSchemaMomentType.java b/src/main/java/components/toolbox/history/commands/AddSchemaMomentType.java new file mode 100644 index 00000000..8daf05af --- /dev/null +++ b/src/main/java/components/toolbox/history/commands/AddSchemaMomentType.java @@ -0,0 +1,27 @@ +package components.toolbox.history.commands; + +import application.history.ModelUserActionCommand; +import components.toolbox.controllers.ToolBoxControllers; +import models.SchemaMomentType; + +public class AddSchemaMomentType extends ModelUserActionCommand { + ToolBoxControllers toolBoxControllers; + SchemaMomentType schemaMomentType; + + public AddSchemaMomentType(ToolBoxControllers tbc, SchemaMomentType smt) { + this.toolBoxControllers = tbc; + this.schemaMomentType = smt; + } + + @Override + public Object execute() { + this.toolBoxControllers.addAMomentType(this.schemaMomentType); + return null; + } + + @Override + public Object undo() { + this.toolBoxControllers.removeAMomentType(this.schemaMomentType); + return null; + } +} diff --git a/src/main/java/components/toolbox/history/commands/RemoveCategoryFromMomentType.java b/src/main/java/components/toolbox/history/commands/RemoveCategoryFromMomentType.java new file mode 100644 index 00000000..c47f6364 --- /dev/null +++ b/src/main/java/components/toolbox/history/commands/RemoveCategoryFromMomentType.java @@ -0,0 +1,28 @@ +package components.toolbox.history.commands; + +import application.history.ModelUserActionCommand; +import models.SchemaCategory; +import models.SchemaMomentType; + +public class RemoveCategoryFromMomentType extends ModelUserActionCommand { + SchemaMomentType smt; + SchemaCategory sc; + + public RemoveCategoryFromMomentType(SchemaMomentType smt, SchemaCategory sc) { + this.smt = smt; + this.sc = sc; + } + + + @Override + public Object execute() { + smt.removeCategory(sc); + return null; + } + + @Override + public Object undo() { + smt.addCategory(sc, -1); + return null; + } +} diff --git a/src/main/java/components/toolbox/history/commands/RemoveSchemaMomentType.java b/src/main/java/components/toolbox/history/commands/RemoveSchemaMomentType.java new file mode 100644 index 00000000..06fe42f0 --- /dev/null +++ b/src/main/java/components/toolbox/history/commands/RemoveSchemaMomentType.java @@ -0,0 +1,27 @@ +package components.toolbox.history.commands; + +import application.history.ModelUserActionCommand; +import components.toolbox.controllers.ToolBoxControllers; +import models.SchemaMomentType; + +public class RemoveSchemaMomentType extends ModelUserActionCommand { + ToolBoxControllers toolBoxControllers; + SchemaMomentType schemaMomentType; + + public RemoveSchemaMomentType(ToolBoxControllers tbc, SchemaMomentType smt) { + this.toolBoxControllers = tbc; + this.schemaMomentType = smt; + } + + @Override + public Object execute() { + this.toolBoxControllers.removeAMomentType(this.schemaMomentType); + return null; + } + + @Override + public Object undo() { + this.toolBoxControllers.addAMomentType(this.schemaMomentType); + return null; + } +} diff --git a/src/main/java/models/ConcreteCategory.java b/src/main/java/models/ConcreteCategory.java index 952f7efe..d5995c2c 100644 --- a/src/main/java/models/ConcreteCategory.java +++ b/src/main/java/models/ConcreteCategory.java @@ -5,7 +5,6 @@ import components.modelisationSpace.property.appCommands.RemoveConcretePropertyCommand; import javafx.beans.property.ListProperty; import javafx.beans.property.SimpleListProperty; -import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableBooleanValue; import javafx.collections.FXCollections; @@ -113,4 +112,5 @@ public ConcreteCategoryController getController() { public void setController(ConcreteCategoryController controller) { this.controller = controller; } + } diff --git a/src/main/java/models/ConcreteProperty.java b/src/main/java/models/ConcreteProperty.java index df4aa22b..32a6a4d7 100644 --- a/src/main/java/models/ConcreteProperty.java +++ b/src/main/java/models/ConcreteProperty.java @@ -29,9 +29,10 @@ public ConcreteProperty(SchemaProperty p, Justification j) { public String getValue() { return value.get(); } public ObservableStringValue valueProperty() { return value; } - public void setValue(String s) { value.set(s); System.out.println("V" + value.get());} + public void setValue(String s) { value.set(s); } public Justification getJustification() { return justification; } public boolean isSchemaProperty(SchemaProperty sp) { return sp == property; } + } diff --git a/src/main/java/models/Moment.java b/src/main/java/models/Moment.java index 47bba38a..54b6e8fe 100644 --- a/src/main/java/models/Moment.java +++ b/src/main/java/models/Moment.java @@ -115,6 +115,23 @@ public Moment(String name, String comment, boolean commentVisible, Justification this.color = new SimpleStringProperty(color); } + public Moment(String name, ObservableList categories, boolean transitional, String color) { + super(); + this.name = new SimpleStringProperty(name); + this.comment = new SimpleStringProperty(); + this.justification = new Justification(); + + this.categories = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + for (SchemaCategory sc : categories) { + addCategory(new ConcreteCategory(sc)); + } + + this.commentVisible = new SimpleBooleanProperty(false); + this.collapsed = new SimpleBooleanProperty(); + this.transitional = new SimpleBooleanProperty(transitional); + this.color = new SimpleStringProperty(color); + } + public void setName(String name) { this.name.set(name); } @@ -150,33 +167,32 @@ public void setTransitional(boolean bool) { } public RootMoment getParent() { return parent;} + + public void setParent(RootMoment parent) { + this.parent = parent; + } + public void addParent(RootMoment parent) {this.parent = parent;} public void addCategory(ConcreteCategory cc) { - categories.add(cc); + boolean added = false; + for (int i = 0; i < categories.size(); i++) { + if (0 < categories.get(i).getName().compareTo(cc.getName())) { + categories.add(i, cc); + added = true; + break; + } + } + if (!added) categories.add(cc); + bindListener(cc); } - public void addCategory(int index, ConcreteCategory cc) { - if(index == categories.size()) { - addCategory(cc); - } - else { - categories.add(index, cc); - bindListener(cc); - } - } public void removeCategory(ConcreteCategory cc) { categories.remove(cc); } public ObservableList concreteCategoriesProperty() { return categories; } - public int indexOfConcreteCategory(ConcreteCategory cc) { - int index = -1; - for(int i = 0; i < categories.size(); i++) - if(categories.get(i) == cc) - return i; - return index; - } + public int indexOfSchemaCategory(SchemaCategory sc) { int index = -1; for(int i = 0; i < categories.size(); i++) @@ -199,14 +215,21 @@ public void changed(ObservableValue observableValue, Boolean } public boolean hadThisCategory(ConcreteCategory category) { - boolean had = false; for (ConcreteCategory concreteCategory : categories) { if (category.getSchemaCategory() == concreteCategory.getSchemaCategory()) { - had = true; - break; + return true; + } + } + return false; + } + + public ConcreteCategory getCategory(ConcreteCategory category) { + for (ConcreteCategory concreteCategory : categories) { + if (category.getSchemaCategory() == concreteCategory.getSchemaCategory()) { + return concreteCategory; } } - return had; + return null; } public int getDepth() { @@ -246,4 +269,8 @@ public boolean isDraggable() { return true; } + public ObservableList getCategories() { + return categories.get(); + } + } diff --git a/src/main/java/models/Project.java b/src/main/java/models/Project.java index 10846165..fafbce34 100644 --- a/src/main/java/models/Project.java +++ b/src/main/java/models/Project.java @@ -1,5 +1,6 @@ package models; +import components.toolbox.controllers.MomentTypeController; import persistency.ProjectSaver; import javafx.beans.property.*; import javafx.beans.value.ObservableValue; @@ -10,6 +11,8 @@ import java.io.IOException; import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; public class Project implements Serializable { @@ -21,6 +24,8 @@ public class Project implements Serializable { private SimpleObjectProperty selectedInterview; + private List momentTypeControllers; + public Project(String name, SchemaTreeRoot baseScheme) { this.name = new SimpleStringProperty(name); this.schemaTreeRoot = new SimpleObjectProperty<>(baseScheme); @@ -29,6 +34,8 @@ public Project(String name, SchemaTreeRoot baseScheme) { this.readOnlyInterviews = new ReadOnlyListWrapper<>(this.interviews); this.selectedInterview = new SimpleObjectProperty<>(); + + this.momentTypeControllers = new LinkedList<>(); } public String getName() { return this.name.get(); } @@ -61,4 +68,11 @@ public void saveAs(String name, String path) throws IOException { ProjectSaver.save(this, path+name); } + public List getMomentTypeControllers() { + return momentTypeControllers; + } + + public void setMomentTypeControllers(List momentTypeControllers) { + this.momentTypeControllers = momentTypeControllers; + } } diff --git a/src/main/java/models/RootMoment.java b/src/main/java/models/RootMoment.java index b14f1353..0e61b8cb 100644 --- a/src/main/java/models/RootMoment.java +++ b/src/main/java/models/RootMoment.java @@ -17,14 +17,18 @@ public RootMoment() { public void addMoment(int index, Moment m) { submoments.add(index, m); + m.setParent(this); } public void addMoment(Moment m) { submoments.add(m); + m.setParent(this); + } public void removeMoment(Moment m) { submoments.remove(m); + m.setParent(null); } public ObservableList momentsProperty() { return submoments; } @@ -37,4 +41,8 @@ public int indexOf(Moment m) { return -1; } + public int numberOfSubMoments() { + return submoments.size(); + } + } diff --git a/src/main/java/models/SchemaCategory.java b/src/main/java/models/SchemaCategory.java index 90df8657..4e46d356 100644 --- a/src/main/java/models/SchemaCategory.java +++ b/src/main/java/models/SchemaCategory.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.LinkedList; -import java.util.List; public class SchemaCategory extends SchemaElement implements IRemovable { diff --git a/src/main/java/models/SchemaElement.java b/src/main/java/models/SchemaElement.java index f3eb4149..88357734 100644 --- a/src/main/java/models/SchemaElement.java +++ b/src/main/java/models/SchemaElement.java @@ -6,10 +6,10 @@ public abstract class SchemaElement implements SchemaTreePluggable { private boolean mustBeRenamed; - private SimpleBooleanProperty expanded; - private StringProperty name; + protected SimpleBooleanProperty expanded; + protected StringProperty name; - SchemaElement(String name) { + public SchemaElement(String name) { this.expanded = new SimpleBooleanProperty(true); this.name = new SimpleStringProperty(name); this.mustBeRenamed = false; diff --git a/src/main/java/models/SchemaFolder.java b/src/main/java/models/SchemaFolder.java index 64a9fa61..208b0a21 100644 --- a/src/main/java/models/SchemaFolder.java +++ b/src/main/java/models/SchemaFolder.java @@ -15,23 +15,26 @@ public class SchemaFolder extends SchemaElement implements IRemovable { public static final DataFormat format = new DataFormat("SchemaFolder"); - private ListProperty categories; - private ListProperty folders; private SimpleBooleanProperty exists; public ListProperty children; + private ListProperty categories; + private ListProperty folders; + private ListProperty momentTypes; public SchemaFolder(String name) { super(name); - this.categories = new SimpleListProperty(FXCollections.observableList(new LinkedList())); - this.folders = new SimpleListProperty(FXCollections.observableList(new LinkedList())); + this.categories = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.momentTypes = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.folders = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); this.exists = new SimpleBooleanProperty(true); - this.children = new SimpleListProperty(FXCollections.observableList(new LinkedList())); + this.children = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); } public final ObservableList categoriesProperty() { return categories; } public final ObservableList foldersProperty() { return folders; } + public final ObservableList momentTypesProperty() { return momentTypes; } public final ObservableList childrenProperty() { return children; } @Override @@ -46,22 +49,17 @@ public boolean isDraggable() { @Override public boolean canContain(SchemaTreePluggable item) { - return (Utils.IsSchemaTreeCategory(item) || Utils.IsSchemaTreeFolder(item)); + return (Utils.IsSchemaTreeCategory(item) || Utils.IsSchemaTreeFolder(item) || Utils.IsSchemaTreeMomentType(item)); } @Override public boolean hasChild(SchemaTreePluggable item) { - return this.children.indexOf(item) != -1; + return this.children.contains(item); } @Override public void addChild(SchemaTreePluggable item) { - if(Utils.IsSchemaTreeCategory(item)) - addCategory((SchemaCategory) item, -1); - else if(Utils.IsSchemaTreeFolder(item)) - addFolder((SchemaFolder) item, -1); - else - throw new IllegalArgumentException("(SchemaFolder::addChild) Can't receive this kind of child ! "); + addChildAt(item, -1); } @Override @@ -70,6 +68,8 @@ public void addChildAt(SchemaTreePluggable item, int index) { addCategory((SchemaCategory) item, index); else if(Utils.IsSchemaTreeFolder(item)) addFolder((SchemaFolder) item, index); + else if(Utils.IsSchemaTreeMomentType(item)) + addMomentType((SchemaMomentType) item, index); else throw new IllegalArgumentException("(SchemaFolder::addChildAt) Can't receive this kind of child ! "); } @@ -80,6 +80,8 @@ public void removeChild(SchemaTreePluggable item) { removeCategory((SchemaCategory) item); else if(Utils.IsSchemaTreeFolder(item)) removeFolder((SchemaFolder) item); + else if(Utils.IsSchemaTreeMomentType(item)) + removeMomentType((SchemaMomentType) item); else throw new IllegalArgumentException("(SchemaFolder::removeChild) Can't remove this kind of child !"); } @@ -90,6 +92,9 @@ public int getChildIndex(SchemaTreePluggable item) { if(r == -1) { r = this.categories.indexOf(item); } + if(r == -1) { + r = this.momentTypes.indexOf(item); + } if(r == -1) throw new IllegalArgumentException("(SchemaFolder::getChildIndex) The provided item is not a child of this element!"); return r; @@ -113,11 +118,9 @@ public boolean canChangeParent() { @Override public void setExists(boolean b) { exists.set(b); - for(SchemaFolder f: folders){ - f.setExists(b); - } - for(SchemaCategory c: categories) - c.setExists(b); + for(SchemaFolder f: folders) f.setExists(b); + for(SchemaCategory c: categories) c.setExists(b); + for(SchemaMomentType mt : momentTypes) mt.setExists(b); } @Override @@ -128,7 +131,7 @@ public ObservableBooleanValue existsProperty() { private void addCategory(SchemaCategory c, int index){ if(index == -1) { categories.add(c); - children.add(c); + children.add(folders.size() + categories.size()-1, c); } else { categories.add(index, c); @@ -149,11 +152,26 @@ private void addFolder(SchemaFolder f, int index){ folders.add(index, f); children.add(index ,f); } - - } private void removeFolder(SchemaFolder f){ folders.remove(f); children.remove(f); } + + private void addMomentType(SchemaMomentType mt, int index) { + if (index == -1) { + momentTypes.add(mt); + children.add(mt); + } + else { + momentTypes.add(index, mt); + children.add(folders.size() + categories.size() +index, mt); + } + } + private void removeMomentType(SchemaMomentType mt){ + momentTypes.remove(mt); + children.remove(mt); + } + + } diff --git a/src/main/java/models/SchemaMomentType.java b/src/main/java/models/SchemaMomentType.java new file mode 100644 index 00000000..05fdceb6 --- /dev/null +++ b/src/main/java/models/SchemaMomentType.java @@ -0,0 +1,203 @@ +package models; + +import application.history.HistoryManager; +import components.schemaTree.Cell.SchemaTreePluggable; +import components.schemaTree.Cell.Utils; +import components.schemaTree.Cell.Visitors.SchemaTreePluggableVisitor; +import components.toolbox.controllers.MomentTypeController; +import components.toolbox.history.commands.RemoveCategoryFromMomentType; +import javafx.beans.property.*; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableBooleanValue; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.input.DataFormat; +import utils.removable.IRemovable; + +import java.util.LinkedList; + +public class SchemaMomentType extends SchemaElement implements IRemovable { + public static final DataFormat format = new DataFormat("SchemaMomentType"); + private SimpleBooleanProperty exists; + private SimpleIntegerProperty nbUsesInModelisation; + + private MomentTypeController momentTypeController; + + private ListProperty categories; + private SimpleBooleanProperty transitional; + private SimpleStringProperty color; + + + public SchemaMomentType(Moment moment, MomentTypeController momentTypeController) { + super(moment.getName()); + super.expanded = new SimpleBooleanProperty(false); + this.exists = new SimpleBooleanProperty(true); + this.nbUsesInModelisation = new SimpleIntegerProperty(0); + this.momentTypeController = momentTypeController; + + this.categories = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + for (int i = 0; i < moment.getCategories().size(); i++) { + addCategory(moment.getCategories().get(i).getSchemaCategory(), -1); + } + + this.transitional = new SimpleBooleanProperty(moment.getTransitional()); + this.color = new SimpleStringProperty(moment.getColor()); + } + + public SchemaMomentType(String name, String color, boolean transitional) { + super(name); + super.expanded = new SimpleBooleanProperty(false); + this.exists = new SimpleBooleanProperty(true); + this.nbUsesInModelisation = new SimpleIntegerProperty(0); + this.momentTypeController = new MomentTypeController(this); + + this.categories = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.transitional = new SimpleBooleanProperty(transitional); + this.color = new SimpleStringProperty(color); + } + + @Override + public boolean canContain(SchemaTreePluggable item) { + return Utils.IsSchemaTreeCategory(item); + } + + @Override + public boolean hasChild(SchemaTreePluggable item) { + return this.categories.contains(item); + } + + @Override + public void addChild(SchemaTreePluggable item) { + if (Utils.IsSchemaTreeCategory(item)) { + addCategory((SchemaCategory)item, -1); + } + else { + throw new IllegalArgumentException("(SchemaMomentType::addChild) Can't receive this kind of child !"); + } + } + + @Override + public void addChildAt(SchemaTreePluggable item, int index) { + if (Utils.IsSchemaTreeCategory(item)) { + addCategory((SchemaCategory)item, index); + } + else { + throw new IllegalArgumentException("(SchemaMomentType::addChildAt) Can't receive this kind of child !"); + } + } + + @Override + public void removeChild(SchemaTreePluggable item) { + if(Utils.IsSchemaTreeCategory(item)) + removeCategory((SchemaCategory)item); + else + throw new IllegalArgumentException("(SchemaProperty::removeChild) Can't receive this kind of child !"); + } + + @Override + public int getChildIndex(SchemaTreePluggable item) { + int r = this.categories.indexOf(item); + if (r == -1) + throw new IllegalArgumentException("(SchemaProperty::addChild) Can't receive this kind of child !"); + return r; + } + + @Override + public void accept(SchemaTreePluggableVisitor visitor) { + visitor.visit(this); + } + + @Override + public boolean canChangeParent() { + return true; + } + + @Override + public boolean mustBeRenamed() { + return false; + } + + @Override + public DataFormat getDataFormat() { + return SchemaMomentType.format; + } + + @Override + public boolean isDraggable() { + return true; + } + + @Override + public String getIconPath() { + return "toolBox_icon.png"; + } + + @Override + public void setExists(boolean b) { + exists.set(b); + } + + @Override + public ObservableBooleanValue existsProperty() { + return exists; + } + + public void setNumberOfUsesInModelisation(int nbUses) { this.nbUsesInModelisation.set(nbUses); } + + public ReadOnlyIntegerProperty numberOfUsesInModelisationProperty() { return this.nbUsesInModelisation; } + + public MomentTypeController getMomentTypeController() { + return momentTypeController; + } + + public void setMomentTypeController(MomentTypeController momentTypeController) { + this.momentTypeController = momentTypeController; + } + + public void addCategory(SchemaCategory sc, int index){ + if(index == -1) { + categories.add(sc); + } + else { + categories.add(index, sc); + } + bindListener(sc); + } + public void removeCategory(SchemaCategory p){ + categories.remove(p); + } + + + private void bindListener(SchemaCategory sc) { + SchemaMomentType smt = this; + sc.existsProperty().addListener(new ChangeListener<>() { + @Override + public void changed(ObservableValue observableValue, Boolean aBoolean, Boolean t1) { + if(!t1){ + HistoryManager.addCommand(new RemoveCategoryFromMomentType(smt, sc), false); + sc.existsProperty().removeListener(this); + } + } + }); + } + + public ListProperty categoriesProperty() { return categories; } + + public ObservableList getCategories() { + return categories.get(); + } + + public Moment createMoment() { + return new Moment(super.getName(), this.categories.get(), this.transitional.get(), this.color.get()); + } + + public boolean getTransitional() { + return transitional.get(); + } + + public String getColor() { + return color.get(); + } + +} diff --git a/src/main/java/models/SchemaTreeRoot.java b/src/main/java/models/SchemaTreeRoot.java index c6e93104..68595115 100644 --- a/src/main/java/models/SchemaTreeRoot.java +++ b/src/main/java/models/SchemaTreeRoot.java @@ -14,93 +14,152 @@ public class SchemaTreeRoot extends SchemaElement { public static final DataFormat format = new DataFormat("SchemaTreeRoot"); + + private ListProperty children; + private ListProperty categories; private ListProperty folders; + private ListProperty momentTypes; public SchemaTreeRoot(String name) { super(name); - this.folders = new SimpleListProperty(FXCollections.observableList(new LinkedList())); + this.categories = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.momentTypes = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.folders = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); + this.children = new SimpleListProperty<>(FXCollections.observableList(new LinkedList<>())); GlobalVariables.getGlobalVariables().setSchemaTreeRoot(this); } + public final ObservableList categoriesProperty() { return categories; } public final ObservableList foldersProperty() { return folders; } + public final ObservableList momentTypesProperty() { return momentTypes; } + public final ObservableList childrenProperty() { return children; } + + @Override + public String toString() { return getName(); } @Override public boolean canContain(SchemaTreePluggable item) { - return Utils.IsSchemaTreeFolder(item); + return (Utils.IsSchemaTreeFolder(item) || Utils.IsSchemaTreeCategory(item) || Utils.IsSchemaTreeMomentType(item)); } @Override public boolean hasChild(SchemaTreePluggable item) { - return this.folders.indexOf(item) != -1; + return this.children.contains(item); } @Override - public void addChild(SchemaTreePluggable item) { - if(Utils.IsSchemaTreeFolder(item)) - addFolder((SchemaFolder)item, -1); - else - throw new IllegalArgumentException("(SchemaTreeRoot::addChild) Can't receive this kind of child !"); + public String getIconPath() { + return "schema.png"; } @Override - public void addChildAt(SchemaTreePluggable item, int index) { - if(Utils.IsSchemaTreeFolder(item)) - addFolder((SchemaFolder)item, index); - else - throw new IllegalArgumentException("(SchemaTreeRoot::addChildAt) Can't receive this kind of child !"); + public DataFormat getDataFormat() { + return SchemaTreeRoot.format; } @Override - public void removeChild(SchemaTreePluggable item) { - if(Utils.IsSchemaTreeFolder(item)) - removeFolder((SchemaFolder)item); - else - throw new IllegalArgumentException("(SchemaTreeRoot::removeChild) Can't remove this kind of child !"); + public boolean isDraggable() { + return false; } @Override - public int getChildIndex(SchemaTreePluggable item) { - int r = this.folders.get().indexOf(item); - if(r == -1) - throw new IllegalArgumentException("(SchemaTreeRoot) The provided item is not a child of this element!"); - return r; + public void accept(SchemaTreePluggableVisitor visitor) { + visitor.visit(this); } @Override - public String getIconPath() { - return "schema.png"; + public boolean canChangeParent() { + return false; } @Override - public DataFormat getDataFormat() { - return SchemaTreeRoot.format; + public void addChild(SchemaTreePluggable item) { + addChildAt(item, -1); } @Override - public boolean isDraggable() { - return false; + public void addChildAt(SchemaTreePluggable item, int index) { + if(Utils.IsSchemaTreeCategory(item)) + addCategory((SchemaCategory) item, index); + else if(Utils.IsSchemaTreeFolder(item)) + addFolder((SchemaFolder) item, index); + else if(Utils.IsSchemaTreeMomentType(item)) + addMomentType((SchemaMomentType) item, index); + else + throw new IllegalArgumentException("(SchemaTreeRoot::addChildAt) Can't receive this kind of child !"); + } @Override - public void accept(SchemaTreePluggableVisitor visitor) { - visitor.visit(this); + public void removeChild(SchemaTreePluggable item) { + if(Utils.IsSchemaTreeCategory(item)) + removeCategory((SchemaCategory) item); + else if(Utils.IsSchemaTreeFolder(item)) + removeFolder((SchemaFolder) item); + else if(Utils.IsSchemaTreeMomentType(item)) + removeMomentType((SchemaMomentType) item); + else + throw new IllegalArgumentException("(SchemaTreeRoot::removeChild) Can't remove this kind of child !"); } @Override - public boolean canChangeParent() { - return false; + public int getChildIndex(SchemaTreePluggable item) { + int r = this.folders.indexOf(item); + if(r == -1) { + r = this.categories.indexOf(item); + } + if(r == -1) { + r = this.momentTypes.indexOf(item); + } + if(r == -1) + throw new IllegalArgumentException("(SchemaTreeRoot) The provided item is not a child of this element!"); + return r; + } + + private void addCategory(SchemaCategory c, int index){ + if(index == -1) { + categories.add(c); + children.add(folders.size() + categories.size()-1, c); + } + else { + categories.add(index, c); + children.add(folders.size() + index, c); + } + } + private void removeCategory(SchemaCategory c){ + categories.remove(c); + children.remove(c); } - public void addFolder(SchemaFolder f, int index){ - if(index == -1) + private void addFolder(SchemaFolder f, int index){ + if(index == -1) { folders.add(f); - else + children.add(folders.size()-1 ,f); + } + else { folders.add(index, f); + children.add(index ,f); + } } - public void removeFolder(SchemaFolder f){ + private void removeFolder(SchemaFolder f){ folders.remove(f); + children.remove(f); } - @Override - public String toString() { return getName(); } + private void addMomentType(SchemaMomentType mt, int index) { + if (index == -1) { + momentTypes.add(mt); + children.add(mt); + } + else { + momentTypes.add(index, mt); + children.add(folders.size() + categories.size() +index, mt); + } + } + private void removeMomentType(SchemaMomentType mt){ + momentTypes.remove(mt); + children.remove(mt); + } + + } diff --git a/src/main/java/persistency/Export/ProjectExporter.java b/src/main/java/persistency/Export/ProjectExporter.java index d5968a82..5fe705a5 100644 --- a/src/main/java/persistency/Export/ProjectExporter.java +++ b/src/main/java/persistency/Export/ProjectExporter.java @@ -73,6 +73,7 @@ protected static String encodeValue(String value) { private static void showExportResult(boolean succeed){ Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle(Configuration.langBundle.getString("export_to_csv")); + alert.getDialogPane().getStylesheets().add(alert.getClass().getResource("/css/application.css").toExternalForm()); alert.setHeaderText(null); if (succeed) { alert.setContentText(Configuration.langBundle.getString("export_success")); diff --git a/src/main/java/persistency/ProjectLoader.java b/src/main/java/persistency/ProjectLoader.java index 462b3144..216d54c8 100644 --- a/src/main/java/persistency/ProjectLoader.java +++ b/src/main/java/persistency/ProjectLoader.java @@ -9,7 +9,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/persistency/newSaveSystem/SMomentTypeController.java b/src/main/java/persistency/newSaveSystem/SMomentTypeController.java new file mode 100644 index 00000000..cd5f2618 --- /dev/null +++ b/src/main/java/persistency/newSaveSystem/SMomentTypeController.java @@ -0,0 +1,53 @@ +package persistency.newSaveSystem; + +import components.toolbox.controllers.MomentTypeController; +import models.SchemaMomentType; +import persistency.newSaveSystem.serialization.ObjectSerializer; +import persistency.newSaveSystem.serialization.Serializable; + +public class SMomentTypeController extends Serializable { + + //General info + public static final int version = 1; + public static final String modelName = "momentTypeController"; + + public SSchemaMomentType schemaMomentType; + + public SMomentTypeController(ObjectSerializer serializer) { + super(serializer); + } + + public SMomentTypeController(ObjectSerializer serializer, MomentTypeController objectReference) { + super(serializer, modelName, version, objectReference); + } + + @Override + public void init(MomentTypeController modelReference) { + schemaMomentType = new SSchemaMomentType(serializer, (SchemaMomentType) modelReference.getSchemaMomentType()); + } + + @Override + protected void addStrategies() { + + } + + @Override + protected void read() { + versionCheck(version, serializer.getInt("@version")); + if (!serializer.getExists("schemaMomentType")) { + schemaMomentType = new SSchemaMomentType(serializer); + serializer.writeObject("schemaMomentType", schemaMomentType); + } + schemaMomentType = serializer.getObject("schemaMomentType", SSchemaMomentType::new); + } + + @Override + protected void write(ObjectSerializer serializer) { + serializer.writeObject("schemaMomentType", schemaMomentType); + } + + @Override + protected MomentTypeController createModel() { + return new MomentTypeController(schemaMomentType.convertToModel()); + } +} diff --git a/src/main/java/persistency/newSaveSystem/SProject.java b/src/main/java/persistency/newSaveSystem/SProject.java index 3c7ed31c..c00206c0 100644 --- a/src/main/java/persistency/newSaveSystem/SProject.java +++ b/src/main/java/persistency/newSaveSystem/SProject.java @@ -1,21 +1,24 @@ package persistency.newSaveSystem; +import components.toolbox.controllers.MomentTypeController; import models.Project; import models.Interview; import persistency.newSaveSystem.serialization.ObjectSerializer; import persistency.newSaveSystem.serialization.Serializable; import java.util.ArrayList; +import java.util.LinkedList; public class SProject extends Serializable { - public static final int version = 1; + public static final int version = 2; public static final String modelName = "project"; public String name; public SSchemaTreeRoot schemaTreeRoot; public ArrayList interviews; public SInterview selectedInterview; + public ArrayList momentTypeControllers; public SProject(ObjectSerializer serializer) { super(serializer); @@ -37,6 +40,11 @@ public void init(Project modelReference) { if(modelReference.getSelectedInterview() != null){ this.selectedInterview = new SInterview(serializer, modelReference.getSelectedInterview()); } + + this.momentTypeControllers = new ArrayList<>(); + for(MomentTypeController mtc : modelReference.getMomentTypeControllers()) { + this.momentTypeControllers.add(new SMomentTypeController(serializer, mtc)); + } } @Override @@ -51,6 +59,12 @@ protected void read() { schemaTreeRoot = serializer.getObject(SSchemaTreeRoot.modelName, SSchemaTreeRoot::new); interviews = serializer.getArray(serializer.setListSuffix(SInterview.modelName), SInterview::new); selectedInterview = serializer.getFacultativeObject("selectedInterview", SInterview::new); + try { + momentTypeControllers = serializer.getArray(serializer.setListSuffix(SMomentTypeController.modelName), SMomentTypeController::new); + } catch (Exception e) { + momentTypeControllers = new ArrayList<>(); + serializer.writeArray(serializer.setListSuffix(SMomentTypeController.modelName), momentTypeControllers); + } } @Override @@ -59,6 +73,7 @@ public void write(ObjectSerializer serializer) { serializer.writeObject(SSchemaTreeRoot.modelName, schemaTreeRoot); serializer.writeArray(serializer.setListSuffix(SInterview.modelName), interviews); serializer.writeFacultativeObject("selectedInterview", selectedInterview); + serializer.writeArray(serializer.setListSuffix(SMomentTypeController.modelName), momentTypeControllers); } @Override @@ -72,6 +87,12 @@ protected Project createModel() { if(selectedInterview != null) p.setSelectedInterview(selectedInterview.convertToModel()); + LinkedList mtcs = new LinkedList(); + for(SMomentTypeController smtc : momentTypeControllers) { + mtcs.add(smtc.createModel()); + } + p.setMomentTypeControllers(mtcs); + return p; } diff --git a/src/main/java/persistency/newSaveSystem/SSchemaCategory.java b/src/main/java/persistency/newSaveSystem/SSchemaCategory.java index 97b4396f..f1c3876c 100644 --- a/src/main/java/persistency/newSaveSystem/SSchemaCategory.java +++ b/src/main/java/persistency/newSaveSystem/SSchemaCategory.java @@ -15,6 +15,7 @@ public class SSchemaCategory extends SSchemaElement { //Fields public ArrayList properties; + public String color; public SSchemaCategory(ObjectSerializer serializer) { super(serializer); @@ -23,7 +24,6 @@ public SSchemaCategory(ObjectSerializer serializer) { public SSchemaCategory(ObjectSerializer serializer, SchemaCategory modelReference) { super(serializer, modelName, version, modelReference); } - public String color; @Override public void init(SchemaCategory modelReference) { diff --git a/src/main/java/persistency/newSaveSystem/SSchemaFolder.java b/src/main/java/persistency/newSaveSystem/SSchemaFolder.java index 9c32fe91..11de9c17 100644 --- a/src/main/java/persistency/newSaveSystem/SSchemaFolder.java +++ b/src/main/java/persistency/newSaveSystem/SSchemaFolder.java @@ -2,7 +2,8 @@ import models.SchemaCategory; import models.SchemaFolder; - +import models.SchemaMomentType; +import org.json.JSONException; import persistency.newSaveSystem.serialization.ObjectSerializer; import java.util.ArrayList; @@ -17,6 +18,7 @@ public class SSchemaFolder extends SSchemaElement { //Fields public ArrayList folders; public ArrayList categories; + public ArrayList momentTypes; public SSchemaFolder(ObjectSerializer serializer) { super(serializer); @@ -30,14 +32,20 @@ public SSchemaFolder(ObjectSerializer serializer, SchemaFolder modelReference) { public void init(SchemaFolder modelReference) { super.init(modelReference); + // WARNING : ORDER IS REALLY IMPORTANT : categories needs to be saved before entering a folder and momentTypes after a folder + this.categories = new ArrayList<>(); + for(SchemaCategory c: modelReference.categoriesProperty()) { + categories.add(new SSchemaCategory(serializer, c)); + } + this.folders = new ArrayList<>(); for(SchemaFolder f: modelReference.foldersProperty()) { folders.add(new SSchemaFolder(serializer, f)); } - this.categories = new ArrayList<>(); - for(SchemaCategory c: modelReference.categoriesProperty()) { - categories.add(new SSchemaCategory(serializer, c)); + this.momentTypes = new ArrayList<>(); + for(SchemaMomentType mt : modelReference.momentTypesProperty()) { + momentTypes.add(new SSchemaMomentType(serializer, mt)); } } @@ -50,8 +58,24 @@ protected void addStrategies() { protected void read() { super.read(); versionCheck(version, serializer.getInt("@version")); - folders = serializer.getArray(serializer.setListSuffix(SSchemaFolder.modelName), SSchemaFolder::new); - categories = serializer.getArray(serializer.setListSuffix(SSchemaCategory.modelName), SSchemaCategory::new); + + try { + folders = serializer.getArray(serializer.setListSuffix(SSchemaFolder.modelName), SSchemaFolder::new); + } catch (JSONException error) { + folders = new ArrayList<>(); + } + + try { + categories = serializer.getArray(serializer.setListSuffix(SSchemaCategory.modelName), SSchemaCategory::new); + } catch (JSONException error) { + categories = new ArrayList<>(); + } + + try { + momentTypes = serializer.getArray(serializer.setListSuffix(SSchemaMomentType.modelName), SSchemaMomentType::new); + } catch (JSONException error) { + momentTypes = new ArrayList<>(); + } } @Override @@ -59,6 +83,7 @@ public void write(ObjectSerializer serializer) { super.write(serializer); serializer.writeArray(serializer.setListSuffix(SSchemaFolder.modelName), folders); serializer.writeArray(serializer.setListSuffix(SSchemaCategory.modelName), categories); + serializer.writeArray(serializer.setListSuffix(SSchemaMomentType.modelName), momentTypes); } @Override @@ -74,6 +99,10 @@ protected SchemaFolder createModel() { folder.addChild(c.convertToModel()); } + for(SSchemaMomentType mt: momentTypes) { + folder.addChild(mt.convertToModel()); + } + return folder; } -} +} \ No newline at end of file diff --git a/src/main/java/persistency/newSaveSystem/SSchemaMomentType.java b/src/main/java/persistency/newSaveSystem/SSchemaMomentType.java new file mode 100644 index 00000000..70c4b4bc --- /dev/null +++ b/src/main/java/persistency/newSaveSystem/SSchemaMomentType.java @@ -0,0 +1,84 @@ +package persistency.newSaveSystem; + +import models.SchemaCategory; +import models.SchemaMomentType; +import org.json.JSONException; +import persistency.newSaveSystem.serialization.ObjectSerializer; + +import java.util.ArrayList; + + +public class SSchemaMomentType extends SSchemaElement { + + //General info + public static final int version = 1; + public static final String modelName = "schemaMomentType"; + + //Fields + public ArrayList categories; + public String color; + public boolean transitional; + + + public SSchemaMomentType(ObjectSerializer serializer) { + super(serializer); + } + + public SSchemaMomentType(ObjectSerializer serializer, SchemaMomentType modelReference) { + super(serializer, modelName, version, modelReference); + } + + @Override + public void init(SchemaMomentType modelReference) { + super.init(modelReference); + this.color = modelReference.getColor(); + this.transitional = modelReference.getTransitional(); + this.categories = new ArrayList<>(); + for (SchemaCategory sc : modelReference.categoriesProperty()) { + this.categories.add((SSchemaCategory) serializer.getSerializationPool().get(sc)); + } + } + + @Override + protected void read() { + super.read(); + versionCheck(version, serializer.getInt("@version")); + categories = serializer.getArray(serializer.setListSuffix(SSchemaCategory.modelName), SSchemaCategory::new); + try { + color = serializer.getString("color"); + } catch (JSONException error) { + color = "ffffff"; + } + try { + transitional = serializer.getBoolean("transitional"); + } catch (JSONException error) { + transitional = false; + } + } + + @Override + protected void write(ObjectSerializer serializer) { + super.write(serializer); + serializer.writeArray(serializer.setListSuffix(SSchemaCategory.modelName), categories); + serializer.writeString("color", color); + serializer.writeBoolean("transitional", transitional); + } + + @Override + protected void addStrategies() { + + } + + @Override + protected SchemaMomentType createModel() { + SchemaMomentType schemaMomentType = new SchemaMomentType(name, color, transitional); + schemaMomentType.expandedProperty().set(expanded); + + for (SSchemaCategory sc : categories) { + schemaMomentType.addChild(sc.convertToModel()); + } + + return schemaMomentType; + } + +} diff --git a/src/main/java/persistency/newSaveSystem/SSchemaTreeRoot.java b/src/main/java/persistency/newSaveSystem/SSchemaTreeRoot.java index 396c9950..0896c382 100644 --- a/src/main/java/persistency/newSaveSystem/SSchemaTreeRoot.java +++ b/src/main/java/persistency/newSaveSystem/SSchemaTreeRoot.java @@ -1,8 +1,7 @@ package persistency.newSaveSystem; -import models.SchemaCategory; -import models.SchemaFolder; -import models.SchemaTreeRoot; +import models.*; +import org.json.JSONException; import persistency.newSaveSystem.serialization.ObjectSerializer; import java.util.ArrayList; @@ -16,6 +15,8 @@ public class SSchemaTreeRoot extends SSchemaElement { //Fields public ArrayList folders; + public ArrayList categories; + public ArrayList momentTypes; public SSchemaTreeRoot(ObjectSerializer serializer) { super(serializer); @@ -28,12 +29,23 @@ public SSchemaTreeRoot(ObjectSerializer serializer, SchemaTreeRoot modelReferenc public void init(SchemaTreeRoot modelReference) { super.init(modelReference); + // WARNING : ORDER IS REALLY IMPORTANT : categories needs to be saved before entering a folder and momentTypes after a folder + this.categories = new ArrayList<>(); + for (SchemaCategory c : modelReference.categoriesProperty()) { + categories.add(new SSchemaCategory(serializer, c)); + } + this.folders = new ArrayList<>(); for(SchemaFolder f: modelReference.foldersProperty()) { folders.add(new SSchemaFolder(serializer, f)); } - } + this.momentTypes = new ArrayList<>(); + for (SchemaMomentType mt: modelReference.momentTypesProperty()) { + momentTypes.add(new SSchemaMomentType(serializer, mt)); + } + + } @Override protected void addStrategies() { @@ -43,13 +55,32 @@ protected void addStrategies() { protected void read() { super.read(); versionCheck(version, serializer.getInt("@version")); - folders = serializer.getArray(serializer.setListSuffix(SSchemaFolder.modelName), SSchemaFolder::new); + + try { + folders = serializer.getArray(serializer.setListSuffix(SSchemaFolder.modelName), SSchemaFolder::new); + } catch (JSONException error) { + folders = new ArrayList<>(); + } + + try { + categories = serializer.getArray(serializer.setListSuffix(SSchemaCategory.modelName), SSchemaCategory::new); + } catch (JSONException error) { + categories = new ArrayList<>(); + } + + try { + momentTypes = serializer.getArray(serializer.setListSuffix(SSchemaMomentType.modelName), SSchemaMomentType::new); + } catch (JSONException error) { + momentTypes = new ArrayList<>(); + } } @Override public void write(ObjectSerializer serializer) { super.write(serializer); serializer.writeArray(serializer.setListSuffix(SSchemaFolder.modelName), folders); + serializer.writeArray(serializer.setListSuffix(SSchemaCategory.modelName), categories); + serializer.writeArray(serializer.setListSuffix(SSchemaMomentType.modelName), momentTypes); } @Override @@ -60,6 +91,14 @@ protected SchemaTreeRoot createModel() { for(SSchemaFolder f: folders){ root.addChild(f.convertToModel()); } + + for(SSchemaCategory c: categories){ + root.addChild(c.convertToModel()); + } + + for(SSchemaMomentType mt: momentTypes) { + root.addChild(mt.convertToModel()); + } return root; } diff --git a/src/main/java/persistency/newSaveSystem/serialization/ObjectSerializer.java b/src/main/java/persistency/newSaveSystem/serialization/ObjectSerializer.java index 53522f2b..7c1ce449 100644 --- a/src/main/java/persistency/newSaveSystem/serialization/ObjectSerializer.java +++ b/src/main/java/persistency/newSaveSystem/serialization/ObjectSerializer.java @@ -10,6 +10,9 @@ public interface ObjectSerializer { static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("d/MM/yyyy"); + + boolean getExists(String setListSuffix); + enum SerializationType { Object, Array }; String getString(String s); diff --git a/src/main/java/persistency/newSaveSystem/serialization/Serializable.java b/src/main/java/persistency/newSaveSystem/serialization/Serializable.java index b87ad4fe..2ccf8a09 100644 --- a/src/main/java/persistency/newSaveSystem/serialization/Serializable.java +++ b/src/main/java/persistency/newSaveSystem/serialization/Serializable.java @@ -1,9 +1,6 @@ package persistency.newSaveSystem.serialization; -import application.configuration.Configuration; import persistency.newSaveSystem.upgrades.UpgradeStrategy; -import utils.popups.OutdatedSoftware; -import utils.popups.WarningPopup; import java.util.HashMap; @@ -115,8 +112,8 @@ protected void finalizeModelCreation(ModelType model) {} protected void versionCheck(int version, int fileversion){ //will prevent the user to launch a file with an outdated software, call in a read() if you want to use it //check SMoment.read() for example - if(version < fileversion) { - OutdatedSoftware.display(Configuration.langBundle.getString("outdated_soft")); + if(version > fileversion) { + serializer.writeInt("@version", version); } } } diff --git a/src/main/java/persistency/newSaveSystem/serialization/json/JSONSerializer.java b/src/main/java/persistency/newSaveSystem/serialization/json/JSONSerializer.java index 4223e680..f03048e6 100644 --- a/src/main/java/persistency/newSaveSystem/serialization/json/JSONSerializer.java +++ b/src/main/java/persistency/newSaveSystem/serialization/json/JSONSerializer.java @@ -149,6 +149,12 @@ public void writeFacultativeObject(String name, Serializable object) { writeObject(name, object); } + public boolean getExists(String name) { + if (jsonObject.has(name)) { + return true; + } + return false; + } @Override public ArrayList getArray(String name, Function serializableCreator) { diff --git a/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyCategory.java b/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyCategory.java index 8f8c1065..500dd351 100644 --- a/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyCategory.java +++ b/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyCategory.java @@ -16,6 +16,11 @@ public Map fetchSuggestions() { for(SchemaFolder folder: GlobalVariables.getSchemaTreeRoot().foldersProperty()) { iterateOverFolder(folder, result); } + + // Loop over the categories + for(SchemaCategory category: GlobalVariables.getSchemaTreeRoot().categoriesProperty()) { + result.put(category.getName(), category); + } return result; } diff --git a/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyProperty.java b/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyProperty.java index a5c8d3aa..3ca283ac 100644 --- a/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyProperty.java +++ b/src/main/java/utils/autoSuggestion/strategies/SuggestionStrategyProperty.java @@ -18,6 +18,12 @@ public Map fetchSuggestions() { for(SchemaFolder folder: GlobalVariables.getSchemaTreeRoot().foldersProperty()) { iterateOverFolder(folder, result); } + + // Loop over the categories of the root + for(SchemaCategory category : GlobalVariables.getSchemaTreeRoot().categoriesProperty()) { + iterateOverCategory(category, result); + } + return result; } diff --git a/src/main/java/utils/popups/MergerPopup.java b/src/main/java/utils/popups/MergerPopup.java new file mode 100644 index 00000000..44624226 --- /dev/null +++ b/src/main/java/utils/popups/MergerPopup.java @@ -0,0 +1,80 @@ +package utils.popups; + +import application.configuration.Configuration; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import utils.DialogState; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +public class MergerPopup implements Initializable { + + private Stage stage; + private DialogState state; + private String instruction; + + @FXML private Label text; + @FXML private Button cancel; + @FXML private Button confirm; + + public MergerPopup(Stage stage, String instruction) { + this.stage = stage; + this.state = DialogState.CLOSED; + this.instruction = instruction; + + + } + @Override + public void initialize(URL location, ResourceBundle resources) { + text.setText(instruction); + confirm.setDefaultButton(true); + + confirm.setOnAction(actionEvent -> { + state = DialogState.SUCCESS; + stage.close(); + }); + + cancel.setOnAction(actionEvent -> { + state = DialogState.CLOSED; + stage.close(); + }); + } + + public static MergerPopup display(String instruction) { + Stage stage = new Stage(StageStyle.UTILITY); + stage.initModality(Modality.APPLICATION_MODAL); + stage.setTitle(Configuration.langBundle.getString("merge_confirmation_title")); + + MergerPopup controller = new MergerPopup(stage, instruction); + + try { + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(controller.getClass().getResource("/views/utils/popups/MergingPopup.fxml")); + loader.setController(controller); + loader.setResources(Configuration.langBundle); + VBox layout = loader.load(); + Scene main = new Scene(layout); + stage.setScene(main); + stage.showAndWait(); + return controller; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + + } + + public DialogState getState() { + return state; + } +} diff --git a/src/main/resources/bundles/Lang_en.properties b/src/main/resources/bundles/Lang_en.properties index 0ac4af7c..b7e60d2d 100644 --- a/src/main/resources/bundles/Lang_en.properties +++ b/src/main/resources/bundles/Lang_en.properties @@ -1,44 +1,20 @@ about_us = About us -acoustic = Acoustic -add_comment = Add a Comment -add_file = Add a File add_interview = Add an Interview -add_moment_here = Add a Moment here -add_moment_here_empty_project = Drag/Drop a moment or an extract of text to create a moment. -add_record = Add Record Files -all_categories = All Categories -all_interviews = All Interviews -all_properties = All Properties cancel = Cancel change_color = Change Color -category_name_invalid = Two categories cannot have the same name -clear_text = Clear Text close = Close color = Color commentaire = Comment confirm = Confirm -confirm_selection = Confirm Selection confirmation_dialog = Confirmation Dialog continue_alert = Do you want to continue? date = Date -default_scheme = Default Scheme -define_ex = Define Extract delete = Delete delete_interview = Delete Interview -delete_interview_text_alert = You are going to delete -delete_moment_text_alert = You are going to delete this moment and all of its children. -delete_warning = Delete Warning display = Display -display_verbatim = Display the Verbatim of the Interview -double_click_add_extract = Double-click to add an extract. -drag_here = Drag a Moment here -duration = Duration (hh:MM - hh:MM) edit = Edit view = View -edit_time = Edit Time edit_interview = Edit Interview -emotional = Emotional -end_time = End Time (hh:MM) enter_project_name = Enter the Name of the Project empty_schema_tree_view = Empty Schema @@ -66,101 +42,50 @@ interviews = Interviews no_interview_selected = No interview selected -error_version = Error, version conflict -error_version_text_alarm = Your saves are in conflict with this new version. -error_version_text_contact = Please contact us in the GitHub repository. -export_ok = Project successfully exported in .csv format, you can find it in your project folder. export_project = Export the Project ... -extract = Interview's Extract file = File -folder_name_invalid = Two folders cannot have the same name format = format : .txt general = General help = Help home = Home interview = Interview (*) or_paste_below = Or paste below -invalid_name = Invalid Name is = is language = Languages link_to_github = Link to GitHub -main_title = PMT - Micro-Phenomenology Modelling Tool -move_moment_here = Move a Moment here name(ID) = Name(ID) name_of_project = Name of the Project new = New new_interview = New Interview moment = Moment new_moment = New Moment -new_moment_name = New moment's name open_project_selected = Open selected project new_project = Create a new Project -ni_in = Type 'Enter' to go to next step, type 'Space' to open a panel, type 'Tab' to focus to next input. -ni_step1 = Step 1. Name of the Interview -ni_step1_input_placeholder = Name of the Interview -ni_step1_ins = What's the name(id) of this Interview ? -ni_step2 = Step 2. Participant of the Interview -ni_step2_ins = Who have participated in this Interview ? -ni_step3 = Step 3. Date of the Interview? -ni_step3_ins = What is the date of the interview ? format: mm/dd/yyyy -ni_step4 = Step 4. Add the Files associated to the Interview -ni_step4_ins = Do you have Files associated ? format: .txt -ni_step4_select = Select the File -ni_step5 = Step 5. Add Comments -no = No -no_category = No Category -no_descripteme = No Descripteme -no_interview = No Interview ok = Ok -ok_text = Are you ok with this? -open = Open open_project = Open recent project open_project_as = Open project from file -other = Other participants = Participant (*) -picture = Picture -properties_name_invalid = Properties from the same category cannot have the same name -quit_alarm = Do you want to save modifications before quitting? quit = Quit recent_project= Recent Projects : -record = Audio or Video Records -recovery = Recovery -recovery_alarm = We detected that the application did not close properly. Do you want to recover a copy of the project that was interrupted? redo = Redo related_scheme = Related Scheme rename = Rename -rename_interview = Rename Interview save_project = Save Project save_project_as = Save Project As ... -save_modification = Modification saved! -select_categories = Select Categories ... -select_extract = Select an Extract select_file = Select a File -select_interviews = Select Interviews ... select_verbatim = Select Verbatim Interview -sensory = Sensory show_comment = Show the comment hide_comment = Hide the comment -start_time = Start time (hh:MM) -stats_category = Stats on categories -moments_comparaison = Comparison between moments of interviews -take_effect_text = This will take effect after restart. -take_effect_text_es = We are currently looking for a translator to translate the software's main features from English to Spanish. \n For the time being, only the English version is available by default. uPMT in english will take effect after restart. -take_effect_text_it = We are currently looking for a translator to translate the software's main features from English to Italian. \n For the time being, only the English version is available by default. uPMT in english will take effect after restart. text_files = Text Files time = Time -time_alert = The time of tools = Tools type = Type(s) undo = Undo userGuide = User Guide -visual = Visual -welcome = Welcome duplicate = Duplicate modify = Modify input = Text entry descripteme_edit = Descripteme editing menu -modify_descripteme = Modify descripteme modify_the_beginning = Modify the beginning: modify_the_end = Modify the end: use = use @@ -182,14 +107,35 @@ scroll_on_reveal = Auto scroll on hover collapse_all_moments = Collapse all moments open_all_moments = Open all moments export_as_png = Export displayed moments as png ... -adjust_zoom_level = Adjust zoom level +adjust_zoom_level = Adjust zoom level alert_unsaved_project = The project has some modifications that aren't saved. Do you want to quit anyway? alert_unsaved_project_title = Unsaved changes alert_unsaved_project_buttonTypeOne = Save and Quit alert_unsaved_project_buttonTypeTwo = Quit without saving transitional_set_off = Turn off transitional transitional_set_on = Turn on transitional -transitional_warning = You can't set a moment as transitional \nwhen it has sub-moments. -outdated_soft = You are using an outdated version of uPMT.\nPlease upgrade to the newest version. +transitional_warning = You can't set a moment as transitional when it has sub-moments. +outdated_soft = You are using an outdated version of uPMT. Please upgrade to the newest version. copy_to_clipboard = Copy to clipboard -color_of_transitional = You can't change the color of a transitional moment! \ No newline at end of file +color_of_transitional = You can't change the color of a transitional moment! +move_under_submoment_warning = You can't move a moment under its sub-moments + +# Merging message +merge_warning = You can't merge from a moment with sub-moments +merge_confirmation_title = Merging confirmation +merge_information_p1 = You are going to merge the moment +merge_information_p2 = in the moment +merge_add_info = At the end of the fusion, this will be added to the moment +merge_add_moment_descriptem = All descriptems from the moment +merge_add_category_p1 = Category +merge_add_category_p2 = with its values and descriptems +merge_add_category_p1_pluriel = Categories +merge_add_category_p2_pluriel = with their values and descriptems +merge_merge_category = will be replaced by that of the moment +merge_be_replaced = will be replaced by +merge_confirmation = Do you confirm these changes ? (You can undo them later) +merge_empty_category_replacement = No properties changed, only descriptemes are replaced + +# Toolbox +show_in_toolbox = Show in toolbox +hide_in_toolbox = Hide in toolbox \ No newline at end of file diff --git a/src/main/resources/bundles/Lang_fr.properties b/src/main/resources/bundles/Lang_fr.properties index 1c756442..8426d207 100644 --- a/src/main/resources/bundles/Lang_fr.properties +++ b/src/main/resources/bundles/Lang_fr.properties @@ -1,48 +1,22 @@ about_us = à propos de nous -acoustic = Sonore -add_comment = Ajouter un commentaire -add_file = Ajouter un fichier add_interview = Ajouter un entretien -add_moment_here = Ajouter un moment ici -add_moment_here_empty_project = Glisser/Déposer un moment ou un extrait de texte pour créer un moment. -add_record = Ajouter des fichiers d'enregistrements -all_categories = Toutes les catégories -all_interviews = Tous les entretiens -all_properties = Toutes les propriétés cancel = Annuler change_color = Changer la couleur -category_name_invalid = Deux catgories ne peuvent pas avoir le mme nom -clear_text = Effacer le texte close = Fermer color = Couleur commentaire = Commentaire confirm = Valider -confirm_selection = Valider la slection confirmation_dialog = Dialogue de confirmation continue_alert = Voulez-vous continuer? date = Date -default_scheme = Schéma par dfaut -define_ex = Définir l'extrait delete = Supprimer delete_interview = Supprimer entretien -delete_interview_text_alert = Vous allez supprimer -delete_moment_text_alert = Vous allez supprimer le moment et tous ses sous-moments. -delete_warning = Avertissement suppression display = Afficher -display_verbatim = Afficher le verbatim de l'entretien -double_click_add_extract = Double-click pour ajouter un extrait. -drag_here = Glisser un moment ici -duration = Dure (hh:MM - hh:MM) edit = Edition view = Affichage edit_interview = Modifier l'interview -edit_time = Modifier le temps -emotional = Emotionnel -end_time = Temps de fin (hh: MM) enter_project_name = Entrez le nom du projet - empty_schema_tree_view = Schéma vide - error = Erreur export_to_csv = Exporter le projet en CSV export_success = Export réussi! @@ -66,103 +40,50 @@ interviews = Entretiens no_interview_selected = Aucun entretien selectionné -error_version = Erreur, conflit de version -error_version_text_alarm = Vos sauvegardes sont en conflit avec la nouvelle version. -error_version_text_contact = Veuillez nous contacter sur le dpt GitHub. -export_ok = Le projet a t export avec succs au format .csv, vous pouvez le retrouver dans le dossier de votre projet. export_project = Exporter le projet ... -extract = Extrait de l'entretien file = Fichier -folder_name_invalid = Deux dossiers ne peuvent pas avoir le mme nom format = format : .txt general = Général help = Aide home = Accueil interview = Entretien (*) or_paste_below = Ou coller ci-dessous -invalid_name = Nom invalide is = est language = Langue link_to_github = Lien vers Github -main_title = PMT - Micro-Phenomenology Modelling Tool -move_moment_here = Déplacer un moment ici -moments_comparaison = Comparison between moments of interviews name(ID) = Nom(ID) name_of_project = Nom du projet new = Nouveau new_interview = Nouvel entretien new_moment = Nouveau Moment -new_moment_name = Nom du nouveau moment moment = Moment new_project = Nouveau projet -ni_in = tapez 'enter' pour aller l'tape suivante, tapez 'espace' pour ouvrir un panneau, tapez 'onglet' pour se concentrer sur l'entre suivante. -ni_step1 = tape 1. Nom de l'interview -ni_step1_input_placeholder = Nom de l'entretien -ni_step1_ins = Quel est le nom (id) de cet entretien? -ni_step2 = tape 2. Participant de l'entretien -ni_step2_ins = Qui a particip cet entretien? -ni_step3 = tape 3. Date de l'entretien? -ni_step3_ins = Quelle est la date de l'entretien? format: mm/jj/aaaa -ni_step4 = tape 4. Ajouter les fichiers associs l'entretien -ni_step4_ins = Avez-vous des fichiers associs? format: .txt -ni_step4_select = Slectionner le fichier -ni_step5 = tape 5. Ajoutez quelques commentaires -no = Non -no_category = Aucune catgorie -no_descripteme = Pas de descripteme -no_interview = Aucun interview ok = Ok -ok_text = tes-vous d'accord avec cela? -open = Ouvert open_project = Projets récents open_project_selected = Ouvrir le projet sélectionné -other = Autre participants = Participant (*) -picture = Image -properties_name_invalid = Les proprits d'une mme catgorie ne peuvent pas avoir le mme nom. -quit_alarm = Voulez-vous sauvegarder avant de quitter ? quit = Quitter recent_project = Projets récents -record = Enregistrements audio ou vido -recovery = Rcupration -recovery_alarm = Nous avons dtect que l'application ne s'est pas ferme correctement. Voulez-vous rcuprer une copie du projet interrompu? redo = Rétablir related_scheme = Schéma associé rename = Renommer -rename_interview = Renommer l'entretien save_project = Sauvegarder le projet -select_categories = Selectionner des catgories ... -select_extract = Choisir un extrait select_file = Choisir un fichier -select_interviews = Slectionner des entretiens ... select_verbatim = Choisir Verbatim entretien -sensory = Sensoriel show_comment = Afficher le commentaire hide_comment = Masquer le commentaire -start_time = Temps de dbut (hh: MM) -stats_category = Statistiques sur les catégories -moments_Comparaison = Comparaison entre moments de plusieurs interviews -take_effect_text = Ceci prendra effet après redémarrage de l'application. -take_effect_text_es = Nous sommes actuellement la recherche de traducteur pour la langue Espagnol. \n La traduction anglaise est disponible par dfaut. Ceci prendra effet aprs redmarrage de l'application. -take_effect_text_it = Nous sommes actuellement la recherche de traducteur pour la langue Italienne. \n La traduction anglaise est disponible par dfaut. Ceci prendra effet aprs redmarrage de l'application. open_project_as = Ouvrir ... save_project_as = Enregistrer sous ... -save_modification = Modification est enregistrée ! text_files = Fichiers texte time = Temps -time_alert = Le temps de tools = Outils type = Type(s) -unable_to_open_project = Impossible d'ouvrir le projet demandé ! undo = Annuler userGuide = Mode d'emploi -visual = Visuel -welcome = Bienvenue duplicate = Dupliquer modify = Modifier input = Saisie descripteme_edit = Edition de descripteme -modify_descripteme = Modifier le descriptème modify_the_beginning = Modifier le début : modify_the_end = Modifier la fin : use = utilisation @@ -184,14 +105,35 @@ scroll_on_reveal = Centrer au survol collapse_all_moments = Collapse tous les moments open_all_moments = Ouvrir tous les moments export_as_png= Exporter les moments visibles en png ... -adjust_zoom_level = Ajuster le zoom +adjust_zoom_level = Ajuster le zoom alert_unsaved_project = Le projet contient des modifications non sauvegardées. Voulez-vous tout de même quitter? alert_unsaved_project_title = Récentes modifications non sauvegardées alert_unsaved_project_buttonTypeOne = Sauvegarder et quitter alert_unsaved_project_buttonTypeTwo = Quitter sans sauvegarder transitional_set_off = Rendre non-transitionnel transitional_set_on = Rendre transitionnel -transitional_warning = Vous ne pouvez pas rendre transitionel\nun moment qui a déjà des sous-moments. -outdated_soft = Vous utilisez une version dépréciée d'uPMT.\nPassez à la dernière version s'il vous plaît. +transitional_warning = Vous ne pouvez pas rendre transitionel un moment qui a déjà des sous-moments. +outdated_soft = Vous utilisez une version dépréciée d'uPMT. Passez à la dernière version s'il vous plaît. copy_to_clipboard = Copier dans le presse-papiers -color_of_transitional = Vous ne pouvez pas changer la couleur d'un moment de transition! \ No newline at end of file +color_of_transitional = Vous ne pouvez pas changer la couleur d'un moment de transition! +move_under_submoment_warning = Vous ne pouvez pas déplacer un moment sous ses sous-moments + +# Merging message +merge_warning = Vous ne pouvez pas fusionner un moment qui a des sous-moments +merge_confirmation_title = Confirmation de fusion +merge_information_p1 = Vous allez fusionner le moment +merge_information_p2 = dans le moment +merge_add_info = A l’issue de la fusion, cela ajoutera au moment +merge_add_moment_descriptem = Tous les descriptèmes du moment +merge_add_category_p1 = La catégorie +merge_add_category_p2 = avec ses valeurs et descriptèmes +merge_add_category_p1_pluriel = Les catégories +merge_add_category_p2_pluriel = avec leurs valeurs et descriptèmes +merge_merge_category = sera remplacée par celle du moment +merge_be_replaced = sera remplacé par +merge_confirmation = Confirmez-vous ces changements ? (Vous pourrez toujours les annuler plus tard) +merge_empty_category_replacement = Aucune propriété changée, seuls les descriptèmes sont remplacés + +# Toolbox +show_in_toolbox = Afficher dans la boîte à outils +hide_in_toolbox = Cacher dans la boîte à outils \ No newline at end of file diff --git a/src/main/resources/css/application.css b/src/main/resources/css/application.css index 3a740316..acd66a63 100644 --- a/src/main/resources/css/application.css +++ b/src/main/resources/css/application.css @@ -1,5 +1,8 @@ /* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */ +* { + -fx-font-family: serif; +} /* -------------------------------------- * -------------------------------------- * --------------SCROLLBAR--------------- @@ -69,9 +72,6 @@ .tree-cell:selected Text{ -fx-fill: black ; } -/*.tree-cell { - -fx-padding: 5px 0em 5px 0em; -}*/ .tree-view-right > .button{ -fx-border-width: 1; @@ -223,7 +223,6 @@ .moment-dnd-zone { -fx-background-radius: 50px; - -fx-background-color: red; } moment-no-left-padding { @@ -434,4 +433,7 @@ Green: #40AC40 #19C519 -fx-background-image: url("/images/btnZoomPlusPng.png"); } +#textInterviewTitle { + -fx-font-size: 22px; +} diff --git a/src/main/resources/css/toolbox.css b/src/main/resources/css/toolbox.css new file mode 100644 index 00000000..36280493 --- /dev/null +++ b/src/main/resources/css/toolbox.css @@ -0,0 +1,32 @@ +/* toolbox */ + +#addMomentTypeFolder { + -fx-background-size: 40 40; + -fx-background-color: rgba(0, 0, 0, 0); + -fx-background-repeat: no-repeat; + -fx-background-position: center; + -fx-background-image: url("/images/toolBox_icon.png"); +} + + +#momentTypeBorderPane { + -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 5, 0, 0, 0); + -fx-background-color: white; + -fx-border-color: transparent; + -fx-border-insets: 3px; + -fx-background-insets: 3px; + -fx-background-radius: 3; + -fx-border-radius:3; +} + +#momentTypeLabel { + -fx-font-weight: bold; +} + +#containerMomentsTypes { + -fx-padding: 5px; +} + +#scrollbarMomentTypes { + -fx-background-color: transparent; +} \ No newline at end of file diff --git a/src/main/resources/images/toolBox_icon.png b/src/main/resources/images/toolBox_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f6965797ce1c2f24ec983d0561aa10afbe36cad9 GIT binary patch literal 11386 zcmeHsbyVBS)^>2(;$Eac@V2-HcP&!fA&>yUA-G#{Ezlyxtyq!bZpE!dibE-Gh2m0p zL(jSQp0mF9pS#xg{&$j{W3D`1&y5lkZ+ll2X^gx9 z29b?<3V96uunDJ+%4gQ9Dv^mujg0PC32tocp4hv)yNkV~zD?RFk0_p8aIU+FVC7r( z)Yv~RT3#OQy}rI3xIIn1_F0^~xaxqj9Fk|=P2V)#?KgQ-uXt{^C{bgiRp9n+;?CJ1 zo3vw{q%m8`=r4LC#~8aw#0@hcXu=Hd|JKhGl_i@+HNyG?lgK^kcwDH zXPBgWy-izkTsD2EY=o^eRCmbEDcvX*lNG6@`T{%)!w{R`-F*4g=`-usMW^dF6@ERl zllhA-iXTO|=VsWS_{D-xm=w*|XAC~WL9U+c;Ez}^mG(yLn1*8l>n3Es>&q)SFKjCgg+b?pP}4r{9{B@y zdQ6?qffR%lakx#@#wawvLY3#eXgmSahVpDe1}*HPwEdAmf=cJKSApn;ihfn{)KdLh zg2Wgd74<}7pAxCRU|H8xS7tq>bRK5eG^`e{ zdaIVpQoN?F$Xb3vZe3Qqp>JJYezsu%;L#W=ubI=|%>W6}xn~|Mj9(wpMGL%s?3wgZ zj>6YWlzWut`1!|CzU!aQo*$a8YiS$Vo$m7$)_hkH`cb`W-%R~t9~Hi;z?9{@11oB` z8EIWO+a1HL*)Y~W*3oFHYO#qaEoj01hRUQMC zXi^-C9&EdA*8O63b=7X1v5Sm-A0aHPy&;mXkXpItb}ZYa~L7tOt2cqM~+Pjio2uyn790G5n%Gd~KFl;M0!h z{kChDU&*t)=cbm(ChOCUMzIe`Q8rbM2M2aS3cR-MGjko*l7>SusDsgli#-nr3GM0@ zb`)~f*M{VwWn5XT&=zocPv~x>Z?!mFaginxyWsTQVO7V@&kw|!wX__JTPyrgak{^x zdtW?u+7;H&x3~Cewm44ifa@rL6vsW{cl zR$=%IQ%)And(IUKm6;*O$(vtD0M#|9<=mtTet1S>fUt-esoW7mzaLqHM%(<2?!g25YH&6SD5Lsk1D*9I{DUmUJ)09%Ls_CX=(I?oWdWXLXir-4w zLW5>GjNUN@b$i=~iR>#^ro)L>1!v>stSalO==`wM@jPk246@-qBln)vkm3@ewvX;E=3l_V4i7C z6{K3(g3Ex>*8t7TsN`@&>jj{*R-~XYY&WL{7!}}uW@Zf02+_+4ctTIJdeMl}VtMe$ zlH!GMLlnmNSxP*)PgEc-CpU$gLjPD$O54IxWPVk*g* zc&F`$w>3T3FI-Z$Ilha0~tu+xY?R@rhLK#gwcS*0U#N>Ih-u=oKMqx>@ zNiJo8p~>LgJ+$*6UPegys#6UaFud$4xyz)RuVeGlB};vFOPz#EvC-^xWo0;@JS+KX zM9O2?b@Vq|M9qznBA6z9*h*_-1+f?*a1#bfcn^J6O0w?$$zk;7-J+{i4=-{<)XdWb zb_e|KSI4{nv_Nr!pS^3*dyfe8)7Rv2WUbLJUb_>Ylr(<+1~Fh-{qd11CC#8F8R@)TlpgPw@L4ia5uFse6uO$lSTJJ{`SAf6$j4mV)$ciy}~X)q@mW z>KE*_W$9<(XTM^W=;Pg;`m2qR8-JQs#7TdMNbxtLyX%o27OP4yQAS;vL-p20em5t< z9*LCSpF-Y0F|cA(9(eeGVN8vM+4HqO%k169-6Z>z6EJ#P&il244P&}uXR_aDF=4=^w815AP zP2M}F$x*LbEGQi9o2E9>fuN$%yvam>RlKoLPS(VekEX%1;nkwUkMZ*YNg_1Q`5r%d zsq1t0!wi$6&25eC?Ghe={PPVSk1da$*R+<^vWti7<^^vfoffK6KBY0G_YaO9g^J2# zezStCHL}e-4{061nIR$yZK>^M7+^~fxlkrk{goD{cL-m?4~}2x(4_F(crP={l29*w z`2oJR%f`rh%U`jvuiRz)6Mq+8Io*^;TK%0qw!ctW`i8eFkN8MGbR|#TmbbG_J7!vU z+aR@KO9;f+WIe~QZDk}OBOK(#gr8ZqkT7#KkQauj5KmzhxJSi=t0SAK1{(0m*+^cH zlzyCw4^Z{dwErbJDF00YbpYu)A-`WGn4b4VTlj0dCBlQ7^?CXY6^ZN*uaGDo-+iw{ ziaXV18Sg@QlFM~~oMiC;o3_b!Q0L-tjqx=IeU7QaV!BoREX13q8&FT`NtX7DP!z-QlEyqtV?szbIb5ZN~i%dnCg(3)C0tVRo7xFi)Pc&LsOK^&k;oO zR-U1zSGABVYfs}OuH_1;zsxf^$ZD0EzKo6KIb|W>% zm`K1kT-!yR?ZeF@HX8tOe{MP3Fv*5ugXF`CuB}Y%EF0` z=Z}Ye4_e6`N12pl?=CeR4VzBj2Ymff^OWO3{+_hFdM_GdXpUEdqC?I~2cs-y13v-Q z>hUQq@rbeg+3Y|YoYQmWl>Naq?g1Lm--*3tYu(g?Iri9NYj}f{)EksSIcxON&$ar| zAob#&S877Ko~k`nFBXQiHR+FzPtdUvU)C1$_!OsvvYtTC*vnvsqEN@pSQ>SV?%|ya zT8-k#_0XSZ)rCSI3HR;MS4d{u7c>TgEnKwYu)vQmCg*IHOFBAYvq8@SUyp}oxZc(~ zUDQpKL6-1?f@idnC-qjIJP)Z-nSIzI-Qg=ZqrVbAN=yBs+tL}}W*7l%nWz6mIF3V~ z$b#qFefl+`XQDdtXGpTCjNAh(!g2|!Rj*|CC$}<9MhT=f^6$cwBCKwV$I>i)`IBCL z+PO1h&V&9k!GdN|-Ja(Rr&r$Ys%@}0-qq&}%MtsLm%Pt+L~5sE$ZTyQu2%elx*xDD z*r|M+-cRMj<5cr>o=RNq&ARf?%ya1i(P`W7RVb23@g1j!=w0#=**Fp0!T@9$(=jV- zcdJ@uri+!q?z56+Oc`Lh&t76kqkh5Yv{rKNC;bQpJVnQzEUYGFc;6Y4T;IHxd%0F$ z=1Qc9M+Q8fp-#Q2+XAZKgrEcUMm7Gu}08e-m*U5UyG5Mow(_Ic?mJ z$po3_TAH*fJyyx+0W1}QWbrFzG)Pu^GF606H_`&ylB*@Pc z7d3W_3(^wz={*l#%h_kDb`P%$JomQj+oY4dAUMJNAac`Ts%|X&(XGtX>I@>Gw%%$v zgT&J>^D&Fr0BDv#HG)Ss*M_G!c&b(kQ}QHe{`K_5*M|*Yn5FHy{FL!HLr$Y)xKugT zaiB9qDU>unqS{_@e>$->CjE`8KR+!I#t6|jTaO)rlqz04`#b$blPGV4xsR2WdOxDn z?QZqnjFz5zIx8IO&t7*ey(tjC(NAernlR6Ldj*w~y&l0yR3{jZDf9 zqGY>G(GRG9Jpt9ve58%D<8u?o{!)2?rW%UNs>x*1L)a;Ud17h?+M#J>a~k~i%}it~ zAn!!lP1BH2H@ifVuOYQPNTbi5z$pOaJ{6FRBOM}jJE6%%jeVn~tT{Rq`XTCq0lN93 zS3cIyX_9IyfcOb4ft$!9drSh&>bPPGylxi1Nq?U4 zc}6Zut(K)l#|f(j4=&*W1>|fK5|s;2fX1$yqdZF3-J~=N-d&d z3^YoyI$Atf@Gzhh|Ivdf52DZCwz8XTFE12P?`%0<)ee>mtcccOfy(>rCX zAv{YTz2)T2P&UZL;PhlnuB4KtcA=RavLVy8!CH8j%%DZOnpCUQj8xtd+ z3mkDexHE(N7mwXAg5N{(N_Y}I2;N~Bqr-wC)4L!MS4)SQz)Wvr_ZEfVSGOyN{fL8B zzj6MnMXFQd040hvQa$5g2Q)mV1f5eUz(v(9*e^5HH!CGI%hF=GyW-N*;;ibH_N6c} z9$b`Ed~W>nqZ6WFy^Kk>#1rI#BF?5PYt;rrj;I%&87=RPkT!Xxd%c(Tkw%eap8k4Y zSAv6v`)$X2emdJ)1n-D)I`+f@7dSMGO~73lESio)keK^vI!`4>VbaCk#wc_#hBA_z zu4_Mv*@hui#cK{Ndq4x~a;o6^$&ahn;P!x{>Pj26@MJ$3fR@2l8+ z&E@vwn||$QUKuKO0#5G_!LBW7b52NYSZ9-kilR9+NCT&7_#pp&d}j@y-{;63E7v1j zI{N@h9bF6od-Vx$8Xfh|HPs{XI|q>$eVKhfNp5RIipe-ghcIbcXqSOwI!0nq#HNMT zLTd8r$tN9^)-?bN_D4+g8;`6EUK{le6h2vsjk@8?@GK4U@7%;ayfMb&UoPUwD*e_@ zb26V=BIHbF;w4(RWX1-mjEi|x5@WgpxPfHEGE={+ENF2+d+e?Dy4f{ERajj4jSOvd z?6iuG5JAf`?OQH8YeC*VlJN+e9l?z8@39WJ$?aD?326G|DpX}c)Mm72VYz2DYBDn+ zQReQ>eGBUB;H~j_oYPXY*B`f=uNdcI?D4kqF)^J%uAky1QBT1Vv@K;bt-gorSH5+= zerFS`)?Y41Ca%^Tvi$vLZhQ`Y6!D2=U0)ZEjBVZuy8>UV>`q4mB3&fxQn4k2g6Z+< zHnUY)ijNg=6 z@4kG*NhbWgWRO$rJ1}HC0DBQ^NsG zF17vDj#|pjgVx2yn9EE>MBp7^?6izvkoYJbc&xg zs{ZLL$*c?C{8%DE6>2<9W(PTnXzIScluQ!u6vQpPNd9f66en9K?{wte+^d6rt0?|) z|1VCpTADv$LH=o|xw#uAfUeTRaEaHe?iCJk;_zl+%8X~GhGtGwz3(5X`SRw{NkHnY z?vA(Pr6=0L6FNYja$Cv-iWxgZt)&vL96H2X0-dB?)nim-mt>xmwmp#$l^519;G{1} zBt?T&znOoR`g6kh!HA)Oy=0x~+CvYql#txnY^kr!;8iKs7C)u+a6{puX67T*!`O?r zD~yo39bd+(a8;%uwWHvX2W*8mMDFEdo-9r;e+GfMlXg^ogzK6ft8_J_R^t z!Q`K-UWUr9yRPu&B$n54TO^&&<{k+9vl@%g>=89c8SRoT-(^jUnZNb)k(d@Q zbQsC+^wUMRKPbsasQFUzMjMcyH_-r_T2^<_J(${^7%L4T_;Df;gY+`PRqGrT*wlh9 z!ouGf62ZkiQ}jfDbPn{a+SEidQaaW41pSQ)DFrJB~w)wjwRcguJdISvp zr28t7-udJ-8TU)+K|L>QHN+dtCU9e2{$}^KG7C3f(2sU%+0mNYLMIG4MW?g}i^m%E zRF=v!aJaBb?e)6iqz=*pv_yIJS1yT;YX@IRux3Hx{_Q?BK7BglW=zjaVp!%(zr1k7 zBQY)K;N@aihyCKCsS3;9SQiNz=q&N3I8|EHFp)GI%$>|xFA**(m~WA+oHr8CsH)9| z!wEz!%8PdlR5ohnTy>$;%~ud@>%xmql}jUvaW_!i-n-Fw(N<(qRIFqeJG?r#LZ;Dt zo{$m#nm3UK)!vKWl1lrX?oqcvZjIMRd9exX;sq2fja?t+HMbA(%ikJrqItv1(XC9Q z1F)ZCPnEURqsYZq>!dCeCkic)ekdJ<5Fg5ELA4C21jBGLrp{wc6)G{Z!k zBjVFCvn1c9sZ@{Iq5fQx=?EJF!;pfiCnFAqW-M5cGz=9un z*q`)DTCF_E`vske+7AL886Qf}RAE{|oBH>uOZp-;O<}z-z;!yDItA+qwrvY~ zN5La29ZgOjA)-3f(`#4-&$&>Y0z+T@cj)ep!PoC9>-^t^^IG(IcmpnNP<2dV^8Gz- zcLi_tLoXe6FKixfq`M}e2`4{*BkLjYQuNv%#*z8Pc%V#JG7jfM_Il+g6YuFT3S@xjI9ep31-4TM$zfUpFe3AZKb^YB3hsJ=U zmBuS{t>6XE;A&HqmuL?&N=k^5>hV4$Vi7P!ubwDmtO&Lm?69goV@!Hbs+(VVAvCTK zib9{{)1BK^G)X3BLJB;HMh&C43`~#|mDL93$&N@CKC=d*%&*+3^A-0VXR<3CoL~2> zjVMF#1IsLKNn?eH-_Ta0$O8aKuV7MAY6?qM342zvW9qyeHl9zb;N(PP_z1`Exi*#IJ6BgnV$@DtJUJ#N8B&%b ze}x>GXpFvJ9_~M!&T;U_i3`(=z6X@($qM3=!Y_$AFCqblL8>WMRaYvlLc&{=mS z6`w9WlP(r7ssQJWP)ag(vPYyq$$RqkN1(UFqXzG$6k}=+229A+s6~>E_0-IfbiP^fKWsMmC;vE%^mF6zz_#BD4U0!BjS1z01y`Qa0Hv%KwW6epq4Ou5#W#Jb|4K5 zA_COmRpwB3l!98pH?~* zaTH`{cXxMZbLVDraJFRU1c5;899-;NT&xHLE8NrG1?<6U52w4Q_=7_l3O9F#Il90c z>}l>f!DbGwE+Rl6Vw~n*@!2^lEB~9`9{#5a2tC+6z>e&kY#i)%cI%KbMOfl^i$ly)$8 zy$?@8S_F9SUl8J84uc5(Zi2bEcsRkFU{(t=9syP!EQ!*5~1XU@e5 z`b`Bf7nF5ywgV%k6J`gtgt9x@TmBxn7hF(6O+f_6#rB8S-#u!!U>6I70b&in>>&>B z@c)1{VRldr7x2BFoP508AP#;W0ZuLf9uT*{e?Zz$XE>r3?^!uH*tq{-zMmLDL^=p* z!S|JlAoy*8$VO1g847lBaMpBiuoVH`hd^_0`Mbbrg#VZpc^Djl@Vu}2KdW8?>h#Cc zAB(^i_Irqi=6B%=g3bSM0tdT6A-^3V?EV-sw*uQ+LJ=$c&yxCAKkR>*E>3d}UI@fO zfR&S%n~#-;Lx77F41qvcIl0VuxDk~Afp9?o&JK65aB&AaLnSN`nIf`5l+f>NXqf*L zljZMtcPr?DU+MdgT>r@RUn%fkf&Zzlf8_eF6!@>e z|5VriH@P1E=ePs4NBjeFM;vBAc}cg3gAlrzlAJW)?*5(KT9ktWJyaiNF&dTC_o|?^qMmU7FBche{D3vU156MHvN%q3Ks*W^&05D65`H?5 z#e`cVyNR&jg54bZQxjBip?HDV?*gtOAnmV5YIu@agW(zsYwx28C2^uBnrP)n-AY0! zwVbT;C>vjY5PX|a7#lF-RK`-SwknH)9$=xRZrz888SE7bKcVR2uu-JKQz%&_*YaXF zroq_`s)(&<9gOtphyNm!jD_>al9i#MVj>|)iU;7~(V*TpSG5PLZu2G!H+8Osf%Z?r zH|Lrd@qX5SB}4w!J@C}5+}a8W|7o7Gs?(^?F&a|I{I?w!h6~+WX-s0XN_1Kpam;X6 zbDiy=37uv|CMl1NLw}(cjh~QmUZ&4zrJ;704V-9c)sU6#KlL3DT#doLJrUk}YGlW0 z8O@>l2onz(IV1pZPjcVv*`Lw6;&4meNki>Pnb9f%=3fD8OL>qahav;OI@{MDZkO<$ z_LyS-4*ps)3Ew|!%<{Uq#@)fP-QGBpXG$y~bwfM`pQG+c*(1zU^lxoyxsd^!ps%DF zvkpf-UEkkw0(l^ro#e8)dW6x^6FOuO)A$?&tXrn^`g+~+$VhbfsL|4R90U>_@0GTZ zkmwX-CQaq#!kNfQa=Cwxvvmz - + -