From 609b896aec9358a43e3def39aef5279f2f2c1180 Mon Sep 17 00:00:00 2001 From: Jonas Schaub <44881147+JonasSchaub@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:46:59 +0200 Subject: [PATCH 1/3] fragmenter instances are now copied to the array in the constructor and also always when a new fragmentation step is added; some renaming and additional documentation; added a note about pipeline fragmenter settings to the tutorial; --- Tutorial/MORTAR_Tutorial.pdf | Bin 8349713 -> 8350286 bytes .../PipelineSettingsViewController.java | 126 +++++++++++------- 2 files changed, 76 insertions(+), 50 deletions(-) diff --git a/Tutorial/MORTAR_Tutorial.pdf b/Tutorial/MORTAR_Tutorial.pdf index 0b20020bd29db2a382c72c240abd5782ee9baf06..d9d38de968a6a7a85e1f531ce277ce91d8798024 100644 GIT binary patch delta 45460 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∠5@Zy0^=CDiXQJ5K|lz>jQcF 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ಳTQ?8V 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 - private final StringProperty pipelineName; + private final StringProperty pipelineNameProperty; /** * Stage of the MainView. */ @@ -83,7 +83,7 @@ public class PipelineSettingsViewController { */ private Stage pipelineSettingsViewStage; /** - * Counts the amount of fragmentation algorithms in the pipeline. + * Counts the amount of fragmentation algorithms in the pipeline. Used for the row numbers in the GUI. */ private int algorithmCounter; /** @@ -93,11 +93,11 @@ public class PipelineSettingsViewController { /** * Array of the available fragmentation algorithms. */ - private final IMoleculeFragmenter[] fragmenters; + private final IMoleculeFragmenter[] availableFragmentersMasterArray; /** * Lists of fragmentation algorithms for the pipeline. */ - private List fragmenterList; + private List selectedPipelineFragmentersList; /** * Boolean to mark if pipeline fragmentation was started from the dialog. */ @@ -107,7 +107,7 @@ public class PipelineSettingsViewController { */ private final boolean isMoleculeDataLoaded; /** - * Boolean value whether a fragmentation is running. + * Boolean value whether a fragmentation is running to disable fragment button if true. */ private final boolean isFragmentationRunning; // @@ -119,8 +119,9 @@ public class PipelineSettingsViewController { private static final Logger LOGGER = Logger.getLogger(PipelineSettingsViewController.class.getName()); // // + // /** - * Constructor. + * Constructor. Opens the view after initialisations. * * @param aMainStage Stage of the MainView * @param aFragmentationService FragmentationService @@ -135,18 +136,26 @@ public PipelineSettingsViewController(Stage aMainStage, IConfiguration aConfiguration) { this.mainStage = aMainStage; this.algorithmCounter = 0; + //to get the existing pipeline from and give the new pipeline to this.fragmentationService = aFragmentationService; - this.fragmenters = this.fragmentationService.getFragmenters(); - this.pipelineName = new SimpleStringProperty(); - this.fragmenterList = new LinkedList<>(); - // copies pipeline fragmenters from fragmentation service to the internal fragmenter list of this class as initialisation + //developers note: this is basically a proxy to make absolutely sure nothing is changed in the fragmentation service + this.availableFragmentersMasterArray = new IMoleculeFragmenter[this.fragmentationService.getFragmenters().length]; + for (int i = 0; i < this.fragmentationService.getFragmenters().length; i++) { + this.availableFragmentersMasterArray[i] = this.fragmentationService.getFragmenters()[i].copy(); + } + //value set in showPipelineSettingsView() + this.pipelineNameProperty = new SimpleStringProperty(); + this.selectedPipelineFragmentersList = new LinkedList<>(); + //copies selected pipeline fragmenters from fragmentation service to the internal fragmenter list of this class this.cancelChangesInFragmenterList(); this.isFragmentationStarted = false; this.isMoleculeDataLoaded = isMoleculeDataLoaded; this.isFragmentationRunning = isFragmentationRunning; this.configuration = aConfiguration; + //other variables are initialised here: this.showPipelineSettingsView(); } + // // // /** @@ -171,7 +180,7 @@ private void showPipelineSettingsView() { Platform.runLater(()->{ this.pipelineSettingsView.addGrid(this.pipelineSettingsViewStage); this.addListenerAndBindings(); - for (IMoleculeFragmenter tmpFragmenter : this.fragmenterList) { + for (IMoleculeFragmenter tmpFragmenter : this.selectedPipelineFragmentersList) { this.addNewChoiceRow(tmpFragmenter.getFragmentationAlgorithmDisplayName(), false); } this.setPipelineName(this.fragmentationService.getPipeliningFragmentationName()); @@ -185,17 +194,18 @@ private void showPipelineSettingsView() { */ private void addListenerAndBindings() { //text field binding - this.pipelineSettingsView.getTextField().textProperty().bindBidirectional(this.pipelineName); + this.pipelineSettingsView.getTextField().textProperty().bindBidirectional(this.pipelineNameProperty); //stage close request this.pipelineSettingsViewStage.setOnCloseRequest(event -> { this.cancelChangesInFragmenterList(); this.pipelineSettingsViewStage.close(); }); - //fragment button + //fragment/run button this.pipelineSettingsView.getFragmentButton().setOnAction(event -> { + //send all changes to fragmentation service but the calling class needs to actually start the fragmentation this.isFragmentationStarted = true; - this.fragmentationService.setPipeliningFragmentationName(this.pipelineName.get()); - this.fragmentationService.setPipelineFragmenter(this.fragmenterList.toArray(new IMoleculeFragmenter[0])); + this.fragmentationService.setPipeliningFragmentationName(this.pipelineNameProperty.get()); + this.fragmentationService.setPipelineFragmenter(this.selectedPipelineFragmentersList.toArray(new IMoleculeFragmenter[0])); this.pipelineSettingsViewStage.close(); }); //cancel button @@ -205,8 +215,8 @@ private void addListenerAndBindings() { }); //apply button this.pipelineSettingsView.getApplyButton().setOnAction(event -> { - this.fragmentationService.setPipeliningFragmentationName(this.pipelineName.get()); - this.fragmentationService.setPipelineFragmenter(this.fragmenterList.toArray(new IMoleculeFragmenter[0])); + this.fragmentationService.setPipeliningFragmentationName(this.pipelineNameProperty.get()); + this.fragmentationService.setPipelineFragmenter(this.selectedPipelineFragmentersList.toArray(new IMoleculeFragmenter[0])); this.pipelineSettingsViewStage.close(); }); //default button @@ -214,37 +224,39 @@ private void addListenerAndBindings() { } // /** - * Adds a new row to the pipeline settings view, which allows to add a new fragmentation algorithms. ComboBox is + * Adds a new row to the pipeline settings view, which allows to add a new fragmentation algorithm. ComboBox is * initially set to fragmentation algorithm corresponding to the given display name. * - * @param aFragmenterDisplayName display name of Fragmenter to initially set ComboBox + * @param aFragmenterDisplayName display name of Fragmenter to initially set ComboBox; if null, the combo box will + * just display a prompt text * @param anUpdateFragmentersList whether the internal fragmenters list should be updated accordingly, e.g. false when * pipeline settings view is constructed for initial display and true when the user adds - * a new row using the "+" button + * a new row using the "+" button; only used when first param is not null */ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFragmentersList) { ComboBox tmpComboBox = new ComboBox<>(); - for (IMoleculeFragmenter tmpFragmenter : this.fragmenters) { + for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { tmpComboBox.getItems().add(tmpFragmenter.getFragmentationAlgorithmDisplayName()); } + //remains if given fragmenter name is null tmpComboBox.setPromptText(Message.get("PipelineSettingsView.comboBox.promptText")); tmpComboBox.setOnAction(anActionEvent -> { - Object tmpSelectedFragmenterString = tmpComboBox.getSelectionModel().getSelectedItem(); + String tmpSelectedFragmenterDisplayName = tmpComboBox.getSelectionModel().getSelectedItem(); int tmpIndex = GridPane.getRowIndex(tmpComboBox) - 1; - for (IMoleculeFragmenter tmpFragmenter : this.fragmenters) { - if (tmpSelectedFragmenterString.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { + for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { + if (tmpSelectedFragmenterDisplayName.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { // will not work cause size of list is set - why not, it is in case a fragmenter that has already been set is changed - if (this.fragmenterList.size() > tmpIndex) { - this.fragmenterList.set(tmpIndex, Arrays.stream(this.fragmenters) - .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterString)).findFirst().orElse(null)); + if (this.selectedPipelineFragmentersList.size() > tmpIndex) { + this.selectedPipelineFragmentersList.set(tmpIndex, Arrays.stream(this.availableFragmentersMasterArray) + .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterDisplayName)).findFirst().get().copy()); } else { - this.fragmenterList.add(Arrays.stream(this.fragmenters) - .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterString)).findFirst().orElse(null)); + this.selectedPipelineFragmentersList.add(Arrays.stream(this.availableFragmentersMasterArray) + .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterDisplayName)).findFirst().get().copy()); } break; } } - if (this.fragmenterList.contains(null)) { + if (this.selectedPipelineFragmentersList.contains(null)) { PipelineSettingsViewController.LOGGER.log(Level.SEVERE, "Error in pipeline fragmenter list, it contains null"); throw new IllegalArgumentException("fragmenter list for pipeline must not contain null"); } @@ -253,14 +265,14 @@ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFrag //does not trigger the action defined above tmpComboBox.getSelectionModel().select(aFragmenterDisplayName); if (anUpdateFragmentersList) { - for (IMoleculeFragmenter tmpFragmenter : this.fragmenters) { + for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { if (aFragmenterDisplayName.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { - this.fragmenterList.add(Arrays.stream(this.fragmenters).filter(x -> - x.getFragmentationAlgorithmDisplayName().equals(aFragmenterDisplayName)).findFirst().orElse(null)); + this.selectedPipelineFragmentersList.add(Arrays.stream(this.availableFragmentersMasterArray).filter(x -> + x.getFragmentationAlgorithmDisplayName().equals(aFragmenterDisplayName)).findFirst().get().copy()); break; } } - if (this.fragmenterList.contains(null)) { + if (this.selectedPipelineFragmentersList.contains(null)) { PipelineSettingsViewController.LOGGER.log(Level.SEVERE, "Error in pipeline fragmenter list, it contains null"); throw new IllegalArgumentException("fragmenter list for pipeline must not contain null"); } @@ -283,14 +295,20 @@ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFrag tmpFragmenterSettingsButton.setOnAction(anActionEvent -> { int tmpFragmenterListIndex = GridPane.getRowIndex(tmpFragmenterSettingsButton) - 1; IMoleculeFragmenter[] tmpArray = new IMoleculeFragmenter[1]; - tmpArray[0] = this.fragmenterList.get(tmpFragmenterListIndex); - FragmentationSettingsViewController tmpFragmentationSettingsViewController - = new FragmentationSettingsViewController(this.pipelineSettingsViewStage, tmpArray, this.fragmenterList.get(tmpFragmenterListIndex).getFragmentationAlgorithmDisplayName(), this.configuration); + tmpArray[0] = this.selectedPipelineFragmentersList.get(tmpFragmenterListIndex); + FragmentationSettingsViewController tmpFragmentationSettingsViewController = new FragmentationSettingsViewController( + this.pipelineSettingsViewStage, + tmpArray, + this.selectedPipelineFragmentersList.get(tmpFragmenterListIndex).getFragmentationAlgorithmDisplayName(), + this.configuration); }); Label tmpLabel = new Label(String.valueOf(++this.algorithmCounter)); //remove removeButton from upper Row if (this.algorithmCounter > 1) { - this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> node instanceof Button button && (GridPane.getRowIndex(node) == this.algorithmCounter - 1) && (button).getText().equals("-") ); + this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> + node instanceof Button button + && (GridPane.getRowIndex(node) == this.algorithmCounter - 1) + && (button).getText().equals("-")); } //remove addButton this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) == this.algorithmCounter); @@ -320,7 +338,8 @@ private void addAddRowButton(int aRowNumber) { tmpAddButton.setMinWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); tmpAddButton.setPrefWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); tmpAddButton.setMaxWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); - tmpAddButton.setOnAction(anActionEvent -> this.addNewChoiceRow(this.fragmentationService.getSelectedFragmenter().getFragmentationAlgorithmDisplayName(), true)); + tmpAddButton.setOnAction(anActionEvent -> + this.addNewChoiceRow(this.fragmentationService.getSelectedFragmenter().getFragmentationAlgorithmDisplayName(), true)); this.pipelineSettingsView.addAddRowButton(tmpAddButton, aRowNumber); } // @@ -350,7 +369,7 @@ private void addRemoveRowButton(int aRowNumber) { this.addAddRowButton(tmpRowIndex); // this.algorithmCounter--; - this.fragmenterList.removeLast(); + this.selectedPipelineFragmentersList.removeLast(); if (this.algorithmCounter > 1) { this.addRemoveRowButton(this.algorithmCounter); } @@ -359,18 +378,22 @@ private void addRemoveRowButton(int aRowNumber) { } // /** - * Cancels changes that are made in the fragmenter list. + * Cancels changes that are made in the fragmenter list. If there is no set pipeline available in the fragmentation + * service, a copy of the selected fragmenter is used to build the new pipeline. Otherwise, the pipeline fragmenters + * from the fragmentation service are copied to the displayed pipeline. The GUI is not(!) updated, neither is + * the algorithm counter. Method to be used for initial synchronisation with the fragmentation service at + * opening of the dialog and if the changes made in the dialog should be cancelled (and the dialog closed). */ private void cancelChangesInFragmenterList() { if (this.fragmentationService.getPipelineFragmenter() == null || this.fragmentationService.getPipelineFragmenter().length < 1) { try { - this.fragmenterList.add(this.fragmentationService.getSelectedFragmenter().copy()); + this.selectedPipelineFragmentersList.add(this.fragmentationService.getSelectedFragmenter().copy()); } catch (Exception anException) { PipelineSettingsViewController.LOGGER.log(Level.SEVERE, anException.toString(), anException); } } else { for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getPipelineFragmenter()) { - this.fragmenterList.add(tmpFragmenter.copy()); + this.selectedPipelineFragmentersList.add(tmpFragmenter.copy()); } } } @@ -388,11 +411,14 @@ private void reset() { //add addButton this.addAddRowButton(2); } - this.fragmenterList = new LinkedList<>(); - this.algorithmCounter = 1; - ComboBox tmpBox = (ComboBox) this.pipelineSettingsView.getGridPane().getChildren().stream().filter(node -> GridPane.getRowIndex(node) == 1 && (node instanceof ComboBox)).findFirst().orElse(null); + this.selectedPipelineFragmentersList = new LinkedList<>(); + this.algorithmCounter = 0; + ComboBox tmpBox = (ComboBox) this.pipelineSettingsView.getGridPane().getChildren().stream().filter(node -> + GridPane.getRowIndex(node) == 1 && (node instanceof ComboBox)).findFirst().orElse(null); if (tmpBox != null) { tmpBox.getSelectionModel().select(this.fragmentationService.getSelectedFragmenter().getFragmentationAlgorithmDisplayName()); + this.selectedPipelineFragmentersList.add(this.fragmentationService.getSelectedFragmenter().copy()); + this.algorithmCounter = 1; } } // @@ -404,7 +430,7 @@ private void reset() { * @return StringProperty */ public StringProperty pipelineNameProperty() { - return this.pipelineName; + return this.pipelineNameProperty; } // /** @@ -413,7 +439,7 @@ public StringProperty pipelineNameProperty() { * @return String pipeline name */ public String getPipelineName() { - return this.pipelineName.get(); + return this.pipelineNameProperty.get(); } // /** @@ -422,7 +448,7 @@ public String getPipelineName() { * @param aName String */ public void setPipelineName(String aName) { - this.pipelineName.set(aName); + this.pipelineNameProperty.set(aName); } // /** @@ -431,7 +457,7 @@ public void setPipelineName(String aName) { * @return true if fragmentation is started */ public boolean isFragmentationStarted() { - return isFragmentationStarted; + return this.isFragmentationStarted; } // } From ef569f14a6776d8cd1448df1b8c97ae49e66d8b7 Mon Sep 17 00:00:00 2001 From: Jonas Schaub <44881147+JonasSchaub@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:30:05 +0200 Subject: [PATCH 2/3] Restructuring and simplification of the code; --- .../PipelineSettingsViewController.java | 229 ++++++++++-------- .../mortar/message/Message_en_GB.properties | 2 + 2 files changed, 124 insertions(+), 107 deletions(-) diff --git a/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java b/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java index 4c6bff54..6449e468 100644 --- a/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java +++ b/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java @@ -31,6 +31,7 @@ import de.unijena.cheminf.mortar.gui.views.PipelineSettingsView; import de.unijena.cheminf.mortar.message.Message; import de.unijena.cheminf.mortar.model.fragmentation.FragmentationService; +import de.unijena.cheminf.mortar.model.fragmentation.algorithm.ErtlFunctionalGroupsFinderFragmenter; import de.unijena.cheminf.mortar.model.fragmentation.algorithm.IMoleculeFragmenter; import javafx.application.Platform; @@ -48,7 +49,6 @@ import javafx.stage.Modality; import javafx.stage.Stage; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; @@ -71,6 +71,22 @@ public class PipelineSettingsViewController { * Configuration class to read resource file paths from. */ private final IConfiguration configuration; + /** + * Service for fragmentation, controls the process of a fragmentation. + */ + private final FragmentationService fragmentationService; + /** + * Boolean value to enable fragment button if molecules are loaded. + */ + private final boolean isMoleculeDataLoaded; + /** + * Boolean value whether a fragmentation is running to disable fragment button if true. + */ + private final boolean isFragmentationRunning; + /** + * Lists of fragmentation algorithms for the pipeline. + */ + private final List selectedPipelineFragmentersList; // // // @@ -83,33 +99,15 @@ public class PipelineSettingsViewController { */ private Stage pipelineSettingsViewStage; /** - * Counts the amount of fragmentation algorithms in the pipeline. Used for the row numbers in the GUI. + * Counts the fragmentation algorithms in the pipeline. Used for the row numbers in the GUI (starting at 1). + * Cannot easily be replaced by a selectedPipelineFragmentersList.size() call because of the initial build up of + * the dialog at initial display. */ private int algorithmCounter; - /** - * Service for fragmentation, controls the process of a fragmentation. - */ - private final FragmentationService fragmentationService; - /** - * Array of the available fragmentation algorithms. - */ - private final IMoleculeFragmenter[] availableFragmentersMasterArray; - /** - * Lists of fragmentation algorithms for the pipeline. - */ - private List selectedPipelineFragmentersList; /** * Boolean to mark if pipeline fragmentation was started from the dialog. */ private boolean isFragmentationStarted; - /** - * Boolean value to enable fragment button if molecules are loaded. - */ - private final boolean isMoleculeDataLoaded; - /** - * Boolean value whether a fragmentation is running to disable fragment button if true. - */ - private final boolean isFragmentationRunning; // // // @@ -124,7 +122,8 @@ public class PipelineSettingsViewController { * Constructor. Opens the view after initialisations. * * @param aMainStage Stage of the MainView - * @param aFragmentationService FragmentationService + * @param aFragmentationService FragmentationService to get existing pipeline from and forward new pipeline to and also + * to get the available fragmenters from * @param isMoleculeDataLoaded boolean whether molecule data is loaded and hence pipeline could be executed * @param isFragmentationRunning boolean whether fragmentation is running * @param aConfiguration configuration instance to read resource file paths from @@ -136,15 +135,8 @@ public PipelineSettingsViewController(Stage aMainStage, IConfiguration aConfiguration) { this.mainStage = aMainStage; this.algorithmCounter = 0; - //to get the existing pipeline from and give the new pipeline to this.fragmentationService = aFragmentationService; - //developers note: this is basically a proxy to make absolutely sure nothing is changed in the fragmentation service - this.availableFragmentersMasterArray = new IMoleculeFragmenter[this.fragmentationService.getFragmenters().length]; - for (int i = 0; i < this.fragmentationService.getFragmenters().length; i++) { - this.availableFragmentersMasterArray[i] = this.fragmentationService.getFragmenters()[i].copy(); - } - //value set in showPipelineSettingsView() - this.pipelineNameProperty = new SimpleStringProperty(); + this.pipelineNameProperty = new SimpleStringProperty(this.fragmentationService.getPipeliningFragmentationName()); this.selectedPipelineFragmentersList = new LinkedList<>(); //copies selected pipeline fragmenters from fragmentation service to the internal fragmenter list of this class this.cancelChangesInFragmenterList(); @@ -177,10 +169,11 @@ private void showPipelineSettingsView() { this.configuration.getProperty("mortar.imagesFolder") + this.configuration.getProperty("mortar.logo.icon.name")).toExternalForm(); this.pipelineSettingsViewStage.getIcons().add(new Image(tmpIconURL)); - Platform.runLater(()->{ + Platform.runLater(() -> { this.pipelineSettingsView.addGrid(this.pipelineSettingsViewStage); this.addListenerAndBindings(); for (IMoleculeFragmenter tmpFragmenter : this.selectedPipelineFragmentersList) { + //update only the GUI, not the internal pipeline fragmenter list, hence false as 2nd param this.addNewChoiceRow(tmpFragmenter.getFragmentationAlgorithmDisplayName(), false); } this.setPipelineName(this.fragmentationService.getPipeliningFragmentationName()); @@ -197,6 +190,7 @@ private void addListenerAndBindings() { this.pipelineSettingsView.getTextField().textProperty().bindBidirectional(this.pipelineNameProperty); //stage close request this.pipelineSettingsViewStage.setOnCloseRequest(event -> { + //note: view and controller are right now discarded after close; so this is not really necessary... this.cancelChangesInFragmenterList(); this.pipelineSettingsViewStage.close(); }); @@ -210,6 +204,7 @@ private void addListenerAndBindings() { }); //cancel button this.pipelineSettingsView.getCancelButton().setOnAction(event -> { + //note: view and controller are right now discarded after close; so this is not really necessary... this.cancelChangesInFragmenterList(); this.pipelineSettingsViewStage.close(); }); @@ -234,50 +229,57 @@ private void addListenerAndBindings() { * a new row using the "+" button; only used when first param is not null */ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFragmentersList) { - ComboBox tmpComboBox = new ComboBox<>(); - for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { - tmpComboBox.getItems().add(tmpFragmenter.getFragmentationAlgorithmDisplayName()); - } - //remains if given fragmenter name is null - tmpComboBox.setPromptText(Message.get("PipelineSettingsView.comboBox.promptText")); - tmpComboBox.setOnAction(anActionEvent -> { - String tmpSelectedFragmenterDisplayName = tmpComboBox.getSelectionModel().getSelectedItem(); - int tmpIndex = GridPane.getRowIndex(tmpComboBox) - 1; - for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { - if (tmpSelectedFragmenterDisplayName.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { - // will not work cause size of list is set - why not, it is in case a fragmenter that has already been set is changed - if (this.selectedPipelineFragmentersList.size() > tmpIndex) { - this.selectedPipelineFragmentersList.set(tmpIndex, Arrays.stream(this.availableFragmentersMasterArray) - .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterDisplayName)).findFirst().get().copy()); - } else { - this.selectedPipelineFragmentersList.add(Arrays.stream(this.availableFragmentersMasterArray) - .filter(x -> x.getFragmentationAlgorithmDisplayName().equals(tmpSelectedFragmenterDisplayName)).findFirst().get().copy()); - } - break; - } - } - if (this.selectedPipelineFragmentersList.contains(null)) { - PipelineSettingsViewController.LOGGER.log(Level.SEVERE, "Error in pipeline fragmenter list, it contains null"); - throw new IllegalArgumentException("fragmenter list for pipeline must not contain null"); - } - }); - if (aFragmenterDisplayName != null) { + ComboBox tmpComboBox = this.newFragmenterComboBox(); + if (aFragmenterDisplayName == null) { + tmpComboBox.setPromptText(Message.get("PipelineSettingsView.comboBox.promptText")); + } else { //does not trigger the action defined above tmpComboBox.getSelectionModel().select(aFragmenterDisplayName); + boolean tmpIsFragmenterFound = false; if (anUpdateFragmentersList) { - for (IMoleculeFragmenter tmpFragmenter : this.availableFragmentersMasterArray) { + for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getFragmenters()) { if (aFragmenterDisplayName.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { - this.selectedPipelineFragmentersList.add(Arrays.stream(this.availableFragmentersMasterArray).filter(x -> - x.getFragmentationAlgorithmDisplayName().equals(aFragmenterDisplayName)).findFirst().get().copy()); + this.selectedPipelineFragmentersList.add(tmpFragmenter.copy()); + tmpIsFragmenterFound = true; break; } } - if (this.selectedPipelineFragmentersList.contains(null)) { - PipelineSettingsViewController.LOGGER.log(Level.SEVERE, "Error in pipeline fragmenter list, it contains null"); + if (!tmpIsFragmenterFound) { + PipelineSettingsViewController.LOGGER.log(Level.SEVERE, () -> String.format("Error in pipeline fragmenter list, " + + "cannot find fragmenter with display name %s.", aFragmenterDisplayName)); throw new IllegalArgumentException("fragmenter list for pipeline must not contain null"); } } } + Button tmpFragmenterSettingsButton = this.newFragmenterSettingsButton(tmpComboBox); + Label tmpLabel = new Label(String.valueOf(++this.algorithmCounter)); + //remove removeButton from upper Row + if (this.algorithmCounter > 1) { + this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> + node instanceof Button button + && (GridPane.getRowIndex(node) == this.algorithmCounter - 1) + && (button).getText().equals(Message.get("PipelineSettingsView.removeRowButton.text"))); + } + //remove addButton (it is alone in the row until this point) + this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) == this.algorithmCounter); + //add new content to row + this.pipelineSettingsView.addAlgorithmChoiceRow(tmpLabel, tmpComboBox, tmpFragmenterSettingsButton, this.algorithmCounter); + //add new remove button to row + if (this.algorithmCounter > 1) { + this.addRemoveRowButton(this.algorithmCounter); + } + //add new add button to next row, +1 cause of next row + this.addAddRowButton(this.algorithmCounter + 1); + } + // + /** + * Creates a new gear button that opens the fragmenter settings. It will be disabled if the selected item of the + * given combo box is null. + * + * @param aComboBox to bind the button's disable property to + * @return the new button + */ + private Button newFragmenterSettingsButton(ComboBox aComboBox) { Button tmpFragmenterSettingsButton = new Button(); tmpFragmenterSettingsButton.setTooltip(GuiUtil.createTooltip(Message.get("PipelineSettingsView.settingButton.toolTip"))); String tmpIconURL = this.getClass().getClassLoader().getResource( @@ -290,7 +292,7 @@ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFrag tmpFragmenterSettingsButton.setMinWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); tmpFragmenterSettingsButton.setPrefWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); tmpFragmenterSettingsButton.setMaxWidth(GuiDefinitions.GUI_PIPELINE_SETTINGS_VIEW_BUTTON_WIDTH_VALUE); - BooleanBinding tmpBooleanBinding = Bindings.isNull(tmpComboBox.getSelectionModel().selectedItemProperty()); + BooleanBinding tmpBooleanBinding = Bindings.isNull(aComboBox.getSelectionModel().selectedItemProperty()); tmpFragmenterSettingsButton.disableProperty().bind(tmpBooleanBinding); tmpFragmenterSettingsButton.setOnAction(anActionEvent -> { int tmpFragmenterListIndex = GridPane.getRowIndex(tmpFragmenterSettingsButton) - 1; @@ -302,24 +304,42 @@ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFrag this.selectedPipelineFragmentersList.get(tmpFragmenterListIndex).getFragmentationAlgorithmDisplayName(), this.configuration); }); - Label tmpLabel = new Label(String.valueOf(++this.algorithmCounter)); - //remove removeButton from upper Row - if (this.algorithmCounter > 1) { - this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> - node instanceof Button button - && (GridPane.getRowIndex(node) == this.algorithmCounter - 1) - && (button).getText().equals("-")); - } - //remove addButton - this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) == this.algorithmCounter); - //add new content to row - this.pipelineSettingsView.addAlgorithmChoiceRow(tmpLabel, tmpComboBox, tmpFragmenterSettingsButton, this.algorithmCounter); - //add new remove button to row - if (this.algorithmCounter > 1) { - this.addRemoveRowButton(this.algorithmCounter); + return tmpFragmenterSettingsButton; + } + // + /** + * Creates a new combo box for choosing a pipeline fragmenter for a specific step. + * + * @return the new combo box + */ + private ComboBox newFragmenterComboBox() { + ComboBox tmpComboBox = new ComboBox<>(); + for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getFragmenters()) { + tmpComboBox.getItems().add(tmpFragmenter.getFragmentationAlgorithmDisplayName()); } - //add new add button to next row - this.addAddRowButton(this.algorithmCounter + 1); //+1 cause of next row + tmpComboBox.setOnAction(anActionEvent -> { + String tmpSelectedFragmenterDisplayName = tmpComboBox.getSelectionModel().getSelectedItem(); + //grid pane row index starts at 1, index of fragmenters list starts at 0 + int tmpIndexInList = GridPane.getRowIndex(tmpComboBox) - 1; + boolean tmpIsFragmenterFound = false; + for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getFragmenters()) { + if (tmpSelectedFragmenterDisplayName.equals(tmpFragmenter.getFragmentationAlgorithmDisplayName())) { + if (this.selectedPipelineFragmentersList.size() > tmpIndexInList) { + this.selectedPipelineFragmentersList.set(tmpIndexInList, tmpFragmenter.copy()); + } else { + this.selectedPipelineFragmentersList.add(tmpFragmenter.copy()); + } + tmpIsFragmenterFound = true; + break; + } + } + if (!tmpIsFragmenterFound) { + PipelineSettingsViewController.LOGGER.log(Level.SEVERE, String.format("Error in pipeline fragmenter list, " + + "cannot find fragmenter with display name %s.", tmpSelectedFragmenterDisplayName)); + throw new IllegalArgumentException("fragmenter list for pipeline must not contain null"); + } + }); + return tmpComboBox; } // /** @@ -330,7 +350,7 @@ private void addNewChoiceRow(String aFragmenterDisplayName, boolean anUpdateFrag private void addAddRowButton(int aRowNumber) { Button tmpAddButton = new Button(); tmpAddButton.setTooltip(GuiUtil.createTooltip(Message.get("PipelineSettingsView.addNewRowButton.toolTip"))); - tmpAddButton.setText("+"); + tmpAddButton.setText(Message.get("PipelineSettingsView.addNewRowButton.text")); tmpAddButton.setStyle("-fx-font-weight: bold"); tmpAddButton.setMinHeight(GuiDefinitions.GUI_BUTTON_HEIGHT_VALUE); tmpAddButton.setPrefHeight(GuiDefinitions.GUI_BUTTON_HEIGHT_VALUE); @@ -351,7 +371,7 @@ private void addAddRowButton(int aRowNumber) { private void addRemoveRowButton(int aRowNumber) { Button tmpRemoveButton = new Button(); tmpRemoveButton.setTooltip(GuiUtil.createTooltip(Message.get("PipelineSettingsView.removeRowButton.toolTip"))); - tmpRemoveButton.setText("-"); + tmpRemoveButton.setText(Message.get("PipelineSettingsView.removeRowButton.text")); tmpRemoveButton.setStyle("-fx-font-weight: bold"); tmpRemoveButton.setMinHeight(GuiDefinitions.GUI_BUTTON_HEIGHT_VALUE); tmpRemoveButton.setPrefHeight(GuiDefinitions.GUI_BUTTON_HEIGHT_VALUE); @@ -367,7 +387,6 @@ private void addRemoveRowButton(int aRowNumber) { this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) == tmpRowIndex); //add addButton this.addAddRowButton(tmpRowIndex); - // this.algorithmCounter--; this.selectedPipelineFragmentersList.removeLast(); if (this.algorithmCounter > 1) { @@ -385,16 +404,24 @@ private void addRemoveRowButton(int aRowNumber) { * opening of the dialog and if the changes made in the dialog should be cancelled (and the dialog closed). */ private void cancelChangesInFragmenterList() { - if (this.fragmentationService.getPipelineFragmenter() == null || this.fragmentationService.getPipelineFragmenter().length < 1) { + this.selectedPipelineFragmentersList.clear(); + if (this.fragmentationService.getPipelineFragmenter() != null || this.fragmentationService.getPipelineFragmenter().length >= 1) { + for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getPipelineFragmenter()) { + try { + this.selectedPipelineFragmentersList.add(tmpFragmenter.copy()); + } catch (Exception anException) { + PipelineSettingsViewController.LOGGER.log(Level.SEVERE, anException.toString(), anException); + } + } + } else { try { this.selectedPipelineFragmentersList.add(this.fragmentationService.getSelectedFragmenter().copy()); } catch (Exception anException) { PipelineSettingsViewController.LOGGER.log(Level.SEVERE, anException.toString(), anException); } - } else { - for (IMoleculeFragmenter tmpFragmenter : this.fragmentationService.getPipelineFragmenter()) { - this.selectedPipelineFragmentersList.add(tmpFragmenter.copy()); - } + } + if (this.selectedPipelineFragmentersList.isEmpty()) { + this.selectedPipelineFragmentersList.add(new ErtlFunctionalGroupsFinderFragmenter()); } } // @@ -403,23 +430,11 @@ private void cancelChangesInFragmenterList() { */ private void reset() { this.setPipelineName(""); - for (int i = 0; i < this.pipelineSettingsView.getGridPane().getChildren().size(); i++) { - //remove addButton - this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) == 2); - //remove complete row content - this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) > 1); - //add addButton - this.addAddRowButton(2); - } - this.selectedPipelineFragmentersList = new LinkedList<>(); + //remove complete row content + this.pipelineSettingsView.getGridPane().getChildren().removeIf(node -> GridPane.getRowIndex(node) > 0); + this.selectedPipelineFragmentersList.clear(); this.algorithmCounter = 0; - ComboBox tmpBox = (ComboBox) this.pipelineSettingsView.getGridPane().getChildren().stream().filter(node -> - GridPane.getRowIndex(node) == 1 && (node instanceof ComboBox)).findFirst().orElse(null); - if (tmpBox != null) { - tmpBox.getSelectionModel().select(this.fragmentationService.getSelectedFragmenter().getFragmentationAlgorithmDisplayName()); - this.selectedPipelineFragmentersList.add(this.fragmentationService.getSelectedFragmenter().copy()); - this.algorithmCounter = 1; - } + this.addNewChoiceRow(this.fragmentationService.getSelectedFragmenterDisplayName(), true); } // // diff --git a/src/main/resources/de/unijena/cheminf/mortar/message/Message_en_GB.properties b/src/main/resources/de/unijena/cheminf/mortar/message/Message_en_GB.properties index 9b5527da..052911ea 100644 --- a/src/main/resources/de/unijena/cheminf/mortar/message/Message_en_GB.properties +++ b/src/main/resources/de/unijena/cheminf/mortar/message/Message_en_GB.properties @@ -231,8 +231,10 @@ PipelineSettingsView.applyButton.toolTip = Applies changes and closes window PipelineSettingsView.textField.promptText = Pipeline Name PipelineSettingsView.comboBox.promptText = Choose fragmentation algorithm PipelineSettingsView.settingButton.toolTip = Fragmenter settings +PipelineSettingsView.removeRowButton.text = - PipelineSettingsView.removeRowButton.toolTip = Remove PipelineSettingsView.addNewRowButton.toolTip = Add +PipelineSettingsView.addNewRowButton.text = + ##HistogramView## HistogramView.title = Histogram HistogramView.cancelButton.text = Close From 96e7fa46d73eba9eac7a006a234f25b5311e87b9 Mon Sep 17 00:00:00 2001 From: Jonas Schaub <44881147+JonasSchaub@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:33:29 +0200 Subject: [PATCH 3/3] Replaced default Ertl fragmenter with copy of first fragmenter in the array of available fragmenters; --- .../mortar/controller/PipelineSettingsViewController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java b/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java index 6449e468..af24f944 100644 --- a/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java +++ b/src/main/java/de/unijena/cheminf/mortar/controller/PipelineSettingsViewController.java @@ -31,7 +31,6 @@ import de.unijena.cheminf.mortar.gui.views.PipelineSettingsView; import de.unijena.cheminf.mortar.message.Message; import de.unijena.cheminf.mortar.model.fragmentation.FragmentationService; -import de.unijena.cheminf.mortar.model.fragmentation.algorithm.ErtlFunctionalGroupsFinderFragmenter; import de.unijena.cheminf.mortar.model.fragmentation.algorithm.IMoleculeFragmenter; import javafx.application.Platform; @@ -421,7 +420,7 @@ private void cancelChangesInFragmenterList() { } } if (this.selectedPipelineFragmentersList.isEmpty()) { - this.selectedPipelineFragmentersList.add(new ErtlFunctionalGroupsFinderFragmenter()); + this.selectedPipelineFragmentersList.add(this.fragmentationService.getFragmenters()[0].copy()); } } //