diff --git a/application/src/test/java/dev/ikm/komet/app/test/ConceptViewModelTest.java b/application/src/test/java/dev/ikm/komet/app/test/ConceptViewModelTest.java index 00f8f278c1..db449f7608 100644 --- a/application/src/test/java/dev/ikm/komet/app/test/ConceptViewModelTest.java +++ b/application/src/test/java/dev/ikm/komet/app/test/ConceptViewModelTest.java @@ -15,7 +15,7 @@ */ package dev.ikm.komet.app.test; -import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModel; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext; import dev.ikm.komet.kview.mvvm.viewmodel.StampViewModel; import dev.ikm.komet.framework.view.ViewProperties; import dev.ikm.komet.framework.window.WindowSettings; @@ -27,9 +27,6 @@ import org.carlfx.cognitive.viewmodel.ViewModel; import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; -import static dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModel.*; -import static dev.ikm.komet.kview.mvvm.viewmodel.StampViewModel.CREATE; -import static dev.ikm.komet.kview.mvvm.viewmodel.StampViewModel.MODE; import static dev.ikm.komet.kview.mvvm.viewmodel.StampViewModel.*; import static dev.ikm.komet.preferences.JournalWindowPreferences.MAIN_KOMET_WINDOW; import static dev.ikm.tinkar.coordinate.stamp.StampFields.PATH; @@ -60,14 +57,11 @@ public static void main(String[] args) { log("Creation stampViewModel \n" + stampViewModel); log("--------------"); - ViewModel conceptViewModel = new ConceptViewModel() - .setPropertyValue(MODE, CREATE) - .setPropertyValue(AXIOM, SUFFICIENT_SET) - .setPropertyValue(CONCEPT_STAMP_VIEW_MODEL, stampViewModel); + ViewModel conceptViewModelNext = new ConceptViewModelNext(); log("--------------"); - log("Creation conceptViewModel \n" + conceptViewModel); + log("Creation conceptViewModel \n" + conceptViewModelNext); log("--------------"); // stop database diff --git a/kview/src/main/java/dev/ikm/komet/kview/controls/skin/KLExpandableNodeListControlSkin.java b/kview/src/main/java/dev/ikm/komet/kview/controls/skin/KLExpandableNodeListControlSkin.java index 902adc1a36..7175722a5f 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/controls/skin/KLExpandableNodeListControlSkin.java +++ b/kview/src/main/java/dev/ikm/komet/kview/controls/skin/KLExpandableNodeListControlSkin.java @@ -249,6 +249,7 @@ private void setExpanded(boolean expanded) { transitionStartValue = getTransition(); if (expanded) { + contentContainer.getChildren().add(hiddenContentContainer); } diff --git a/kview/src/main/java/dev/ikm/komet/kview/events/AddFullyQualifiedNameEvent.java b/kview/src/main/java/dev/ikm/komet/kview/events/AddFullyQualifiedNameEvent.java deleted file mode 100644 index 9bca8b646c..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/events/AddFullyQualifiedNameEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.events; - -import dev.ikm.tinkar.events.Evt; -import dev.ikm.tinkar.events.EvtType; -import dev.ikm.komet.framework.view.ViewProperties; - -public class AddFullyQualifiedNameEvent extends Evt { - - public static final EvtType ADD_FQN = new EvtType<>(Evt.ANY, "ADD_FQN"); - - private ViewProperties viewProperties; - - /** - * Constructs a prototypical Event. - * - * @param source the object on which the Event initially occurred - * @param eventType - * @param viewProperties - */ - public AddFullyQualifiedNameEvent(Object source, EvtType eventType, ViewProperties viewProperties) { - super(source, eventType); - this.viewProperties = viewProperties; - } - - public ViewProperties getViewProperties() { - return viewProperties; - } - - public void setViewProperties(ViewProperties viewProperties) { - this.viewProperties = viewProperties; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/events/AddOtherNameToConceptEvent.java b/kview/src/main/java/dev/ikm/komet/kview/events/AddOtherNameToConceptEvent.java deleted file mode 100644 index ed860f3604..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/events/AddOtherNameToConceptEvent.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.events; - -import dev.ikm.tinkar.events.Evt; -import dev.ikm.tinkar.events.EvtType; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.tinkar.common.id.PublicId; - -public class AddOtherNameToConceptEvent extends Evt { - - public static final EvtType ADD_DESCRIPTION = new EvtType<>(Evt.ANY, "ADD_DESCRIPTION"); - - private PublicId publicId; - private ViewProperties viewProperties; - - public AddOtherNameToConceptEvent(Object source, EvtType eventType) { - super(source, eventType); - } - - /** - * Constructs a prototypical Event. - * - * @param source source of the event - * @param eventType type of the event - * @param viewProperties payload needed to for the Edit Other Name Form - */ - public AddOtherNameToConceptEvent(Object source, EvtType eventType, ViewProperties viewProperties) { - super(source, eventType); - this.viewProperties = viewProperties; - } - - /** - * Constructs a prototypical Event. - * - * @param source source of the event - * @param eventType type of the event - */ - public AddOtherNameToConceptEvent(Object source, EvtType eventType, PublicId publicId) { - super(source, eventType); - this.publicId = publicId; - } - - public PublicId getPublicId() { - return publicId; - } - - public void setPublicId(PublicId publicId) { - this.publicId = publicId; - } - - public ViewProperties getViewProperties() { - return viewProperties; - } - - public void setViewProperties(ViewProperties viewProperties) { - this.viewProperties = viewProperties; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/events/EditConceptFullyQualifiedNameEvent.java b/kview/src/main/java/dev/ikm/komet/kview/events/EditConceptFullyQualifiedNameEvent.java deleted file mode 100644 index 4875f69a42..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/events/EditConceptFullyQualifiedNameEvent.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.events; - -import dev.ikm.tinkar.events.Evt; -import dev.ikm.tinkar.events.EvtType; -import dev.ikm.komet.kview.mvvm.model.DescrName; -import dev.ikm.tinkar.common.id.PublicId; - -public class EditConceptFullyQualifiedNameEvent extends Evt { - - public static final EvtType EDIT_FQN = new EvtType<>(Evt.ANY, "EDIT_FQN"); - - private final PublicId publicId; - - private final DescrName descrName; - - /** - * Constructs a prototypical Event. - * - * @param source the object on which the Event initially occurred - * @param eventType the edit event type - * @param publicId publicId of the concept being edited. - * @throws IllegalArgumentException if source is null - */ - public EditConceptFullyQualifiedNameEvent(Object source, EvtType eventType, PublicId publicId) { - super(source, eventType); - this.publicId = publicId; - this.descrName = null; - } - - /** - * Constructs a prototypical Event. - * - * @param source the object on which the Event initially occurred - * @param eventType the edit event type - * @param descrName the model object. - * @throws IllegalArgumentException if source is null - */ - public EditConceptFullyQualifiedNameEvent(Object source, EvtType eventType, DescrName descrName) { - super(source, eventType); - this.publicId = null; - this.descrName = descrName; - } - - public PublicId getPublicId() { - return publicId; - } - - public DescrName getDescrName() { - return descrName; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/events/EditOtherNameConceptEvent.java b/kview/src/main/java/dev/ikm/komet/kview/events/EditOtherNameConceptEvent.java deleted file mode 100644 index 2176401902..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/events/EditOtherNameConceptEvent.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.events; - -import dev.ikm.tinkar.events.Evt; -import dev.ikm.tinkar.events.EvtType; -import dev.ikm.komet.kview.mvvm.model.DescrName; -import dev.ikm.tinkar.common.id.PublicId; - -public class EditOtherNameConceptEvent extends Evt { - - public static final EvtType EDIT_OTHER_NAME = new EvtType<>(Evt.ANY, "EDIT_OTHER_NAME"); - - private final PublicId publicId; - - private final DescrName descrName; - - /** - * Constructs EditOtherNameConceptEvent with needed PublicId payload - * @param source source of the event - * @param eventType type of the event - * @param publicId payload needed to for the Edit Other Name Form - */ - public EditOtherNameConceptEvent(Object source, EvtType eventType, PublicId publicId) { - super(source, eventType); - this.publicId = publicId; - this.descrName = null; - } - - /** - * Constructs EditOtherNameConceptEvent with needed PublicId payload - * @param source source of the event - * @param eventType type of the event - * @param descrName the model object. - */ - public EditOtherNameConceptEvent(Object source, EvtType eventType, DescrName descrName) { - super(source, eventType); - this.publicId = null; - this.descrName =descrName; - } - - public PublicId getPublicId() { - return publicId; - } - - public DescrName getDescrName() { - return descrName; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/klwindows/concept/ConceptKlWindow.java b/kview/src/main/java/dev/ikm/komet/kview/klwindows/concept/ConceptKlWindow.java index 4ee13394ab..728257cd98 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/klwindows/concept/ConceptKlWindow.java +++ b/kview/src/main/java/dev/ikm/komet/kview/klwindows/concept/ConceptKlWindow.java @@ -19,26 +19,41 @@ import dev.ikm.komet.framework.activity.ActivityStream; import dev.ikm.komet.framework.activity.ActivityStreamOption; import dev.ikm.komet.framework.activity.ActivityStreams; +import dev.ikm.komet.framework.controls.EntityLabelWithDragAndDrop; import dev.ikm.komet.framework.view.ViewProperties; import dev.ikm.komet.kview.klwindows.AbstractEntityChapterKlWindow; import dev.ikm.komet.kview.klwindows.EntityKlWindowState; import dev.ikm.komet.kview.klwindows.EntityKlWindowType; import dev.ikm.komet.kview.klwindows.EntityKlWindowTypes; +import dev.ikm.komet.kview.mvvm.view.concept.ConceptController; import dev.ikm.komet.kview.mvvm.view.concept.ConceptNode; import dev.ikm.komet.kview.mvvm.view.concept.ConceptNodeFactory; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext.ConceptPropertyKeys; import dev.ikm.komet.preferences.KometPreferences; import dev.ikm.tinkar.common.alert.AlertStreams; +import dev.ikm.tinkar.common.flow.FlowSubscriber; import dev.ikm.tinkar.common.id.PublicIdStringKey; import dev.ikm.tinkar.common.id.PublicIds; import dev.ikm.tinkar.common.util.uuid.UuidT5Generator; +import dev.ikm.tinkar.entity.Entity; import dev.ikm.tinkar.terms.EntityFacade; +import javafx.application.Platform; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ChangeListener; +import javafx.scene.layout.BorderPane; import javafx.scene.layout.Pane; +import org.carlfx.cognitive.loader.Config; +import org.carlfx.cognitive.loader.FXMLMvvmLoader; +import org.carlfx.cognitive.loader.JFXNode; +import org.carlfx.cognitive.loader.NamedVm; import org.eclipse.collections.api.factory.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.UUID; +import static dev.ikm.komet.kview.fxutils.CssHelper.defaultStyleSheet; import static dev.ikm.komet.kview.mvvm.viewmodel.FormViewModel.CREATE; import static dev.ikm.komet.kview.mvvm.viewmodel.FormViewModel.MODE; @@ -55,6 +70,14 @@ public class ConceptKlWindow extends AbstractEntityChapterKlWindow { private final ConceptNode conceptNode; private final PublicIdStringKey detailsActivityStreamKey; + private final JFXNode conceptJFXNode; + private final ConceptViewModelNext conceptViewModelNext = new ConceptViewModelNext(); + + // + protected final SimpleObjectProperty entityFocusProperty = new SimpleObjectProperty<>(); + protected FlowSubscriber invalidationSubscriber; + protected ChangeListener entityFocusChangeListener; + // /** * Constructs a new {@code ConceptKlWindow}. * @@ -76,37 +99,79 @@ public ConceptKlWindow(UUID journalTopic, EntityFacade entityFacade, // Create a unique key for the details activity stream. this.detailsActivityStreamKey = new PublicIdStringKey<>(PublicIds.of(uuid.toString()), uniqueDetailsTopic); - ActivityStreams.create(detailsActivityStreamKey); + ActivityStreams.create(detailsActivityStreamKey); // TODO: we ignore the return value here?? test what we get returned to understand the actual streamKey type + + // create a unique topic for each concept detail instance + UUID conceptTopic = UUID.randomUUID(); + + // Create a ConceptViewModel with preSet Propertys + + NamedVm conceptViewModelNext = new NamedVm("conceptViewModelNext", this.conceptViewModelNext); + conceptViewModelNext.viewModel() + .setValue(ConceptPropertyKeys.VIEW_PROPERTIES, viewProperties) + .setValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT, isCreateMode) + .setValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, entityFacade) + .setValue(ConceptPropertyKeys.ASOCIATED_JOURNAL_WINDOW_TOPIC, journalTopic) + .setValue(ConceptPropertyKeys.THIS_UNIQUE_CONCEPT_TOPIC, conceptTopic) + .reset(); // make sure that View values are init + + Config conceptConfig = new Config(ConceptController.class.getResource(ConceptController.CONCEPT_DETAILS_VIEW_FXML_FILE)).addNamedViewModel(conceptViewModelNext); + + this.conceptJFXNode = FXMLMvvmLoader.make(conceptConfig); + + LOG.info(conceptViewModelNext.viewModel().toString()); + this.conceptJFXNode.controller().updateView(); + + // Programmatically change CSS Theme + this.conceptJFXNode.node().getStylesheets().clear(); + String styleSheet = defaultStyleSheet(); + this.conceptJFXNode.node().getStylesheets().add(styleSheet); + + // Initialize the DetailsNode with a factory. KometNodeFactory conceptDetailsNodeFactory = new ConceptNodeFactory(); this.conceptNode = (ConceptNode) conceptDetailsNodeFactory.create(viewProperties.parentView(), - detailsActivityStreamKey, + detailsActivityStreamKey, // TODO: understand - we create a activity stream and we asociated the PUBLISH option to it. The two other options are subscribe / sync ActivityStreamOption.PUBLISH.keyForOption(), AlertStreams.ROOT_ALERT_STREAM_KEY, true, journalTopic); // Configure the details node if we are in create mode. - if (isCreateMode) { - conceptNode.getConceptDetailsViewController() - .getConceptViewModel() - .setPropertyValue(MODE, CREATE); - conceptNode.getConceptDetailsViewController().updateView(); - } +// if (isCreateMode) { +// conceptNode.getConceptDetailsViewController() +// .getConceptViewModel() +// .setPropertyValue(MODE, CREATE); +// conceptNode.getConceptDetailsViewController().updateView(); +// } + // TODO: wtf is this late update mechanism // This will refresh the Concept details, history, timeline conceptNode.handleActivity(Lists.immutable.of(entityFacade)); // Getting the concept window pane - this.paneWindow = (Pane) conceptNode.getNode(); + paneWindow = this.conceptJFXNode.node(); // Set the onClose callback for the details window. - conceptNode.getConceptDetailsViewController().setOnCloseConceptWindow(detailsController -> { - ActivityStreams.delete(detailsActivityStreamKey); - getOnClose().ifPresent(Runnable::run); - // TODO more clean up such as view models and listeners just in case (memory). + conceptJFXNode.controller().setOnCloseConceptWindow( + detailsController -> { + ActivityStreams.delete(detailsActivityStreamKey); + getOnClose().ifPresent(Runnable::run); + // TODO more clean up such as view models and listeners just in case (memory). + } + ); + + this.conceptViewModelNext.getViewProperties().nodeView().addListener((obs, oldViewCoord, newViewCoord) -> { + if (newViewCoord != null) { + LOG.info("refresh concept window when view coordinate has changed." + newViewCoord); + //updateView(); // this was the ConceptController refresh + this.conceptViewModelNext.reset(); // TODO: verify how this is working + } }); + + + //conceptNode.getConceptDetailsViewController().setOnCloseConceptWindow(); } /** @@ -118,14 +183,6 @@ public PublicIdStringKey getDetailsActivityStreamKey() { return detailsActivityStreamKey; } - /** - * Returns the {@link ConceptNode} associated with this window. - * - * @return the {@link ConceptNode} used for concept viewing or editing - */ - public ConceptNode getDetailsNode() { - return conceptNode; - } @Override public EntityKlWindowType getWindowType() { @@ -134,25 +191,106 @@ public EntityKlWindowType getWindowType() { @Override protected boolean isPropertyPanelOpen() { - return conceptNode.getConceptDetailsViewController().isPropertiesPanelOpen(); + return conceptJFXNode.controller().isPropertiesPanelOpen(); } @Override protected void setPropertyPanelOpen(boolean isOpen) { - conceptNode.getConceptDetailsViewController().setPropertiesPanelOpen(isOpen); + conceptJFXNode.controller().setPropertiesPanelOpen(isOpen); } @Override protected String selectedPropertyPanel() { - String pane = conceptNode.getPropertiesViewController().selectedView(); - LOG.debug("saving with Concept " + pane); - return pane; + // TODO: get viewModel via Concept node and save / restore property window that way + //String pane = conceptNode.getPropertiesViewController().selectedView(); + //LOG.debug("saving with Concept " + pane); + //return pane; + return "TODO"; } @Override protected void setSelectedPropertyPanel(String selectedPanel) { + // TODO: get viewModel via Concept node and save / restore property window that way LOG.debug("restoring pane with "+ selectedPanel); - conceptNode.getPropertiesViewController().restoreSelectedView(selectedPanel); + //conceptNode.getPropertiesViewController().restoreSelectedView(selectedPanel); + } + + // For ConceptNode in the case that Concept should not be displayed on the journalView + public BorderPane getConceptBorderPane() { + return this.conceptJFXNode.node(); + } + + public ConceptController getConceptController() { + return this.conceptJFXNode.controller(); + } + + private void listenOnEntityFacadeUpdate() { + // remove later when closing + this.entityFocusChangeListener = (observable, oldEntityFacade, newEntityFacade) -> { + LOG.info("Concept Entity Facade changed"); + + if (newEntityFacade != null) { + + if (newEntityFacade == oldEntityFacade) { + LOG.info("WE GOT UPDATE ON ENTITY FACADE WITHOUT ANYTHING CHANGING!"); + } + + // TODO: what was ConceptNode title and tooltip used for + //titleProperty.set(viewProperties.calculator().getPreferredDescriptionTextWithFallbackOrNid(newEntityFacade)); + //toolTipTextProperty.set(viewProperties.calculator().getFullyQualifiedDescriptionTextWithFallbackOrNid(newEntityFacade)); + + // forceupdating the Model with new state + conceptViewModelNext.setValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, newEntityFacade); + + + // Populate Detail View +// if (getConceptDetailsViewController() != null) { +// getConceptDetailsViewController() +// .getConceptViewModel() +// .setPropertyValue(CURRENT_ENTITY, newEntityFacade); +// getConceptDetailsViewController().updateView(); +// } + + // Populate Properties View + // +// if (getPropertiesViewController() != null) { +// getPropertiesViewController().updateModel(viewProperties, newEntityFacade); +// getPropertiesViewController().updateView(); +// } + + // Populate Timeline View //TODO: dont forget abotu timeline reset here +// if (getTimelineViewController() != null) { +// getTimelineViewController().resetConfigPathAndModules(); +// getTimelineViewController().updateModel(viewProperties, newEntityFacade); +// getTimelineViewController().updateView(); +// } + + } else { + // Show a blank view (nothing selected) + //titleProperty.set(EntityLabelWithDragAndDrop.EMPTY_TEXT); + //toolTipTextProperty.set(EntityLabelWithDragAndDrop.EMPTY_TEXT); + conceptViewModelNext.setValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, newEntityFacade); + //getConceptDetailsViewController().clearView(); + //getPropertiesViewController().clearView(); // does nothing currently + // getPropertiesViewController().updateModel(viewProperties, newEntityFacade); // TODO: updates history/hirarchy controller + } + + }; + + // When a new entity is selected populate the view. An entity has been selected upstream (activity stream) + this.entityFocusProperty.addListener(this.entityFocusChangeListener); + + // If database updates the underlying entity, this will do a force update of the UI. + this.invalidationSubscriber = new FlowSubscriber<>(nid -> { + if (entityFocusProperty.get() != null && entityFocusProperty.get().nid() == nid) { + // component has changed, need to update. + Platform.runLater(() -> entityFocusProperty.set(null)); + Platform.runLater(() -> entityFocusProperty.set(Entity.provider().getEntityFast(nid))); + } + }); + + // Register to the Entity Service + Entity.provider().addSubscriberWithWeakReference(this.invalidationSubscriber); } } diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescrName.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescrName.java index 2670557818..f740a83731 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescrName.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/model/DescrName.java @@ -40,8 +40,6 @@ public class DescrName { private ConceptEntity language; - - // the public ID of the description semantic that this class represents private PublicId semanticPublicId; diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptController.java index d9b6250903..1099887162 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptController.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptController.java @@ -33,8 +33,9 @@ import dev.ikm.komet.kview.fxutils.SlideOutTrayHelper; import dev.ikm.komet.kview.mvvm.model.DescrName; import dev.ikm.komet.kview.mvvm.view.journal.VerticallyFilledPane; -import dev.ikm.komet.kview.mvvm.view.properties.PropertiesController; -import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModel; +import dev.ikm.komet.kview.mvvm.view.timeline.TimelineController; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext.*; import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase; import dev.ikm.komet.preferences.KometPreferences; import dev.ikm.tinkar.common.id.PublicId; @@ -48,12 +49,15 @@ import dev.ikm.tinkar.events.Subscriber; import dev.ikm.tinkar.terms.*; import javafx.application.Platform; -import javafx.beans.InvalidationListener; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ObservableList; import javafx.css.PseudoClass; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; import javafx.geometry.Side; import javafx.scene.Node; import javafx.scene.control.*; @@ -64,13 +68,14 @@ import javafx.scene.shape.SVGPath; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; -import org.carlfx.cognitive.loader.InjectViewModel; -import org.carlfx.cognitive.viewmodel.ValidationViewModel; +import javafx.stage.Stage; +import org.carlfx.cognitive.loader.*; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.list.ImmutableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; @@ -80,6 +85,7 @@ import java.util.function.Consumer; import static dev.ikm.komet.kview.events.ClosePropertiesPanelEvent.CLOSE_PROPERTIES; +import static dev.ikm.komet.kview.fxutils.CssHelper.defaultStyleSheet; import static dev.ikm.komet.kview.fxutils.IconsHelper.IconType.ATTACHMENT; import static dev.ikm.komet.kview.fxutils.IconsHelper.IconType.COMMENTS; import static dev.ikm.komet.kview.fxutils.MenuHelper.fireContextMenuEvent; @@ -88,10 +94,7 @@ import static dev.ikm.komet.kview.fxutils.window.DraggableSupport.addDraggableNodes; import static dev.ikm.komet.kview.fxutils.window.DraggableSupport.removeDraggableNodes; import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.*; -import static dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModel.*; -import static dev.ikm.komet.kview.mvvm.viewmodel.FormViewModel.MODE; import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.FORM_TIME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.IS_CONFIRMED_OR_SUBMITTED; import static dev.ikm.tinkar.common.service.PrimitiveData.PREMUNDANE_TIME; import static dev.ikm.tinkar.common.util.time.DateTimeUtil.PREMUNDANE; import static dev.ikm.tinkar.coordinate.stamp.StampFields.*; @@ -102,6 +105,9 @@ import static dev.ikm.tinkar.terms.TinkarTerm.*; public class ConceptController { + public static final String CONCEPT_DETAILS_VIEW_FXML_FILE = "concept-details.fxml"; + + private static final String CONCEPT_TIMELINE_VIEW_FXML_FILE = "timeline.fxml"; private static final PseudoClass STAMP_SELECTED = PseudoClass.getPseudoClass("selected"); @@ -237,25 +243,29 @@ public class ConceptController { /** * A function from the caller. This class passes a boolean true if classifier button is pressed invoke caller's function to be returned a view. */ + + // TODO: feature or bug?: this links the "reasonorToggleButton" from journal.fxml / JournalController with this button + // e.g if this controller toggle is activated -> slideOut also the global reasonnerToggleButton + // slideIn is the same logic. E.g if local state is different make the globalState the same + // if both are the same state nothing changes + + // this functionality is only used in Concept. Not in pattern/semantic private Consumer reasonerResultsControllerConsumer; - private PropertiesController propertiesController; + + +// @InjectViewModel +// private ConceptViewModel conceptViewModel; @InjectViewModel - private ConceptViewModel conceptViewModel; + private ConceptViewModelNext conceptViewModelNext; private EvtBus eventBus; private UUID conceptTopic; - private Subscriber editConceptFullyQualifiedNameEventSubscriber; - - private Subscriber addFullyQualifiedNameEventSubscriber; - private Subscriber editOtherNameConceptEventSubscriber; private Subscriber editConceptEventSubscriber; - private Subscriber addOtherNameToConceptEventSubscriber; - private Subscriber closePropertiesPanelEventSubscriber; private Subscriber createConceptEventSubscriber; @@ -278,59 +288,29 @@ public class ConceptController { private boolean isUpdatingStampSelection = false; - public ConceptController() { - } + // + private JFXNode propertiesJFXNode; - public ConceptController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; + private TimelineController timelineController; + private Pane timelinePane; + + public ConceptController() { } @FXML public void initialize() { - stampViewControl.selectedProperty().subscribe(this::onStampSelectionChanged); - identiconImageView.setOnContextMenuRequested(contextMenuEvent -> { - // query all available memberships (semantics having the purpose as 'membership', and no fields) - // query current concept's membership semantic records. - // build menuItems according to 'add' or 'remove' , style to look like figma designs style classes. - // show offset to the right of the identicon - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); - EntityFacade currentConceptFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); - List patterns = getMembershipPatterns(); - ContextMenu membershipContextMenu = new ContextMenu(); - membershipContextMenu.getStyleClass().add("kview-context-menu"); + setupNodes(); - Comparator patternMenuComparator = (m1, m2) -> m1.getText().compareToIgnoreCase(m2.getText()); - List addedMenuItems = new ArrayList<>(); - List removedMenuItems = new ArrayList<>(); - for (PatternEntityVersion pattern : patterns) { - MenuItem menuItem = new MenuItem(); - if (isInMembershipPattern(currentConceptFacade.nid(), pattern.nid(), viewCalculator)) { - menuItem.setText("Remove from " + pattern.entity().description()); - menuItem.setOnAction(evt -> removeFromMembershipPattern(currentConceptFacade.nid(), pattern.entity(), viewCalculator)); - addedMenuItems.add(menuItem); - } else { - menuItem.setText("Add to " + pattern.entity().description()); - menuItem.setOnAction(evt -> addToMembershipPattern(currentConceptFacade, pattern.entity(), viewCalculator)); - removedMenuItems.add(menuItem); - } - } - if (!addedMenuItems.isEmpty()) { - // sort the added (able to be removed) - addedMenuItems.sort(patternMenuComparator); - membershipContextMenu.getItems().addAll(addedMenuItems); - // then add a menu line separator - if (!removedMenuItems.isEmpty()) { - membershipContextMenu.getItems().add(new SeparatorMenuItem()); - } - } - // then add the sorted removed (that can be added) - removedMenuItems.sort(patternMenuComparator); - membershipContextMenu.getItems().addAll(removedMenuItems); + setupTimelineBindings(); + setupPropertyBindings(); + + setupConceptHeader(); + + setupDetailsBanner(); + setupDetailsNameSemantics(); + setupAxioms(); - membershipContextMenu.show(identiconImageView, contextMenuEvent.getScreenX(), - contextMenuEvent.getSceneY() + identiconImageView.getFitHeight()); - }); Tooltip.install(fqnTitleText, conceptNameTooltip); @@ -338,121 +318,114 @@ public void initialize() { eventBus = EvtBusFactory.getDefaultEvtBus(); - // when the user clicks a fully qualified name, open the PropertiesPanel - editConceptFullyQualifiedNameEventSubscriber = evt -> { - if (!propertiesToggleButton.isSelected()) { - propertiesToggleButton.fire(); - } - setStampSelectedSilently(false); - }; - eventBus.subscribe(conceptTopic, EditConceptFullyQualifiedNameEvent.class, editConceptFullyQualifiedNameEventSubscriber); - - addFullyQualifiedNameEventSubscriber = evt -> { - if (!propertiesToggleButton.isSelected()) { - propertiesToggleButton.fire(); - } - setStampSelectedSilently(false); - }; - eventBus.subscribe(conceptTopic, AddFullyQualifiedNameEvent.class, addFullyQualifiedNameEventSubscriber); - - // when the user clicks one of the other names, open the PropertiesPanel - editOtherNameConceptEventSubscriber = evt -> { - if (!propertiesToggleButton.isSelected()) { - propertiesToggleButton.fire(); - } - setStampSelectedSilently(false); - }; - eventBus.subscribe(conceptTopic, EditOtherNameConceptEvent.class, editOtherNameConceptEventSubscriber); - - addOtherNameToConceptEventSubscriber = evt -> { - if (!propertiesToggleButton.isSelected()) { - propertiesToggleButton.fire(); - } - setStampSelectedSilently(false); - }; - eventBus.subscribe(conceptTopic, AddOtherNameToConceptEvent.class, addOtherNameToConceptEventSubscriber); + conceptViewModelNext.getViewProperties().nodeView().subscribe(() -> { + clearView(); + updateView(); + }); - // if the user clicks the Close Properties Button from the Edit Descriptions panel - // in that state, the properties bump out will be slid out, therefore firing will perform a slide in - closePropertiesPanelEventSubscriber = evt -> { - propertiesToggleButton.fire(); - setStampSelectedSilently(false); - }; - eventBus.subscribe(conceptTopic, ClosePropertiesPanelEvent.class, closePropertiesPanelEventSubscriber); // Listener when user enters a new fqn - ObservableList fullyQualifiedNames = getConceptViewModel().getObservableList(FULLY_QUALIFIED_NAMES); - fullyQualifiedNames.addListener((InvalidationListener) observable -> { - if (!fullyQualifiedNames.isEmpty()) { - DescrName fqnDescrName = fullyQualifiedNames.get(0); - updateConceptBanner(); + ObservableList fqnFacades = conceptViewModelNext.getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS); + fqnFacades.subscribe( () -> { + SimpleBooleanProperty hasValidStampProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + if (hasValidStampProp.getValue()) { + // TODO: make sure updateConceptBanner equivalent is there + updateFullyQualifiedNamesDescription(fqnFacades); + } else { + LOG.error("Stamp not valid -> Cannot update FQN description"); } - updateFullyQualifiedNamesDescription(fullyQualifiedNames); - }); - ObservableList otherNames = getConceptViewModel().getObservableList(OTHER_NAMES); - otherNames.addListener((InvalidationListener) obs -> { - if (!otherNames.isEmpty()) { - propertiesController.setHasOtherName(true); + }); +// ObservableList fullyQualifiedNames = getConceptViewModel().getObservableList(FULLY_QUALIFIED_NAMES); +// fullyQualifiedNames.addListener((InvalidationListener) observable -> { +// if (!fullyQualifiedNames.isEmpty()) { +// DescrName fqnDescrName = fullyQualifiedNames.get(0); +// updateConceptBanner(); +// } +// updateFullyQualifiedNamesDescription(fullyQualifiedNames); +// }); + + ObservableList otherNameFacades = conceptViewModelNext.getObservableList(ConceptViewModelNext.ConceptPropertyKeys.ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS); + otherNameFacades.subscribe( () -> { + SimpleBooleanProperty hasValidStampProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + + if (hasValidStampProp.getValue()) { + updateOtherNamesDescription(otherNameFacades); + } else { + LOG.error("Stamp not valid -> Cannot update otherName description"); } - updateOtherNamesDescription(otherNames); }); - // Listens for events related to new fqn or other names added to this concept. Subscriber is responsible for - // the final create concept transaction. - createConceptEventSubscriber = evt -> { - DescrName descrName = evt.getModel(); +// // TODO: This is a wired binding we may want to reconstruct that +// ObservableList otherNames = getConceptViewModel().getObservableList(OTHER_NAMES); +// otherNames.addListener((InvalidationListener) obs -> { +// if (!otherNames.isEmpty()) { +// propertiesController.setHasOtherName(true); +// } +// updateOtherNamesDescription(otherNames); +// }); - if (getConceptViewModel() == null || descrName == null) { - LOG.warn("ViewModel should not be null. Event type:" + evt.getEventType()); - return; - } - if (CREATE.equals(conceptViewModel.getPropertyValue(MODE))) { - if (evt.getEventType() == CreateConceptEvent.ADD_FQN) { - fullyQualifiedNames.clear(); - fullyQualifiedNames.add(descrName); - } else if (evt.getEventType() == CreateConceptEvent.ADD_OTHER_NAME) { - otherNames.add(descrName); - }else if (evt.getEventType() == CreateConceptEvent.EDIT_OTHER_NAME) { // Since we are - updateOtherNamesDescription(otherNames); - }else { // Since we are - updateFullyQualifiedNamesDescription(fullyQualifiedNames); - } - // Attempts to write data - boolean isWritten = conceptViewModel.createConcept(propertiesController.getStampFormViewModel()); - // when written the mode changes to EDIT. - LOG.info("Is " + conceptViewModel + " created? " + isWritten); - if (isWritten) { - updateView(); - } - // remove 'Add Fully Qualified Name' from the menu - setUpDescriptionContextMenu(addDescriptionButton); - //TODO revisit: why should the mode ever be edit inside a create event? - } else if (EDIT.equals(conceptViewModel.getPropertyValue(MODE))){ - conceptViewModel.addOtherName(conceptViewModel.getViewProperties().calculator().viewCoordinateRecord().editCoordinate(), descrName); - otherNames.add(descrName); - } + // TODO: down below the outcommented code listend fro each AddFqn EditFqn AddOther and EditOther + // TODO: it provided mostly a DescrName with the call, that was then pluged back into + // TODO: what we just need is to handle the case when a user "creates a new FQN or otherName with the UI Button" + // TODO: since the case when a user clicks on a existing one is handeld via the above subscribers - }; - eventBus.subscribe(conceptTopic, CreateConceptEvent.class, createConceptEventSubscriber); + // Listens for events related to new fqn or other names added to this concept. Subscriber is responsible for + // the final create concept transaction. +// createConceptEventSubscriber = evt -> { +// DescrName descrName = evt.getModel(); +// +// if (getConceptViewModel() == null || descrName == null) { +// LOG.warn("ViewModel should not be null. Event type:" + evt.getEventType()); +// return; +// } +// +// if (CREATE.equals(conceptViewModel.getPropertyValue(MODE))) { +// if (evt.getEventType() == CreateConceptEvent.ADD_FQN) { +// fullyQualifiedNames.clear(); +// fullyQualifiedNames.add(descrName); +// } else if (evt.getEventType() == CreateConceptEvent.ADD_OTHER_NAME) { +// otherNames.add(descrName); +// }else if (evt.getEventType() == CreateConceptEvent.EDIT_OTHER_NAME) { // Since we are +// updateOtherNamesDescription(otherNames); +// }else { // Since we are +// updateFullyQualifiedNamesDescription(fullyQualifiedNames); +// } +// // Attempts to write data +// boolean isWritten = conceptViewModel.createConcept(propertiesController.getStampFormViewModel()); +// // when written the mode changes to EDIT. +// LOG.info("Is " + conceptViewModel + " created? " + isWritten); +// if (isWritten) { +// updateView(); +// } +// // remove 'Add Fully Qualified Name' from the menu +// setUpDescriptionContextMenu(addDescriptionButton); +// //TODO revisit: why should the mode ever be edit inside a create event? +// } else if (EDIT.equals(conceptViewModel.getPropertyValue(MODE))){ +// conceptViewModel.addOtherName(conceptViewModel.getViewProperties().calculator().viewCoordinateRecord().editCoordinate(), descrName); +// otherNames.add(descrName); +// } +// +// }; +// eventBus.subscribe(conceptTopic, CreateConceptEvent.class, createConceptEventSubscriber); // set up the event handler for editing a concept - editConceptEventSubscriber = evt -> { - DescrName descrName = evt.getModel(); - - if (getConceptViewModel() == null || descrName == null) { - LOG.warn("ViewModel should not be null. Event type:" + evt.getEventType()); - return; - } - if (EDIT.equals(conceptViewModel.getPropertyValue(MODE))) { - if (evt.getEventType() == EditConceptEvent.EDIT_FQN) { - // the listener will fire on the FQN when we update this - fullyQualifiedNames.add(descrName); - } - } - }; - eventBus.subscribe(conceptTopic, EditConceptEvent.class, editConceptEventSubscriber); +// editConceptEventSubscriber = evt -> { +// DescrName descrName = evt.getModel(); +// +// if (getConceptViewModel() == null || descrName == null) { +// LOG.warn("ViewModel should not be null. Event type:" + evt.getEventType()); +// return; +// } +// if (EDIT.equals(conceptViewModel.getPropertyValue(MODE))) { +// if (evt.getEventType() == EditConceptEvent.EDIT_FQN) { +// // the listener will fire on the FQN when we update this +// fullyQualifiedNames.add(descrName); +// } +// } +// }; +// eventBus.subscribe(conceptTopic, EditConceptEvent.class, editConceptEventSubscriber); // listen to rules changes to update the axioms @@ -475,6 +448,7 @@ public void initialize() { conceptContentScrollPane.pseudoClassStateChanged(V_SCROLLBAR_NEEDED, isVerticalScrollbarVisible(conceptContentScrollPane))); // TODO: When event bus is more universally used the database can emit events. For now we listen for a refresh calculator events + // TODO: this can be moved into the Node Later and we can have there a clean ExternalUpdate <--> ConceptViewModel update // Refresh Concept window refreshCalculatorEventSubscriber = _ -> { LOG.info("Refresh concept window details"); @@ -504,35 +478,284 @@ public void initialize() { updateView(); } }; - EvtBusFactory.getDefaultEvtBus().subscribe(conceptViewModel.getPropertyValue(CURRENT_JOURNAL_WINDOW_TOPIC), + EvtBusFactory.getDefaultEvtBus().subscribe(conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_UNIQUE_CONCEPT_TOPIC), GenEditingEvent.class, refreshSubscriber); - conceptViewModel.getViewProperties().nodeView().addListener((obs, oldViewCoord, newViewCoord) -> { - if (newViewCoord != null) { - LOG.info("refresh concept window when view coordinate has changed." + newViewCoord); - updateView(); + + + + // TODO: this is wrong it should be -> when we have a entityFacade we cannot edit anymore ever right? + SimpleObjectProperty thisFacade = conceptViewModelNext.getProperty(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); + BooleanBinding nonEditableAxiom = thisFacade.isNotNull(); + addAxiomButton.visibleProperty().bind(nonEditableAxiom); + + // this through bindings is handeld in the properties controller itself, simmilar on how overall window state is handeld +// hasValidStampProp.subscribe((isValidStamp) -> { +// if( isValidStamp) { // we can now bind the values directly +// // TODO instead of this mumble jumble between Concept and Propertie Controller do the right thing +// //propertiesController +// } else { // we can only show "default stamp" values +// +// } +// }); + + // in create mode we do not have a stamp by default, thats why the first thing we need to archive + // is having a valid stamp. Hold anyting else until that. + + + + +// conceptViewModel.getProperty(MODE).subscribe(() -> { +// propertiesController.setEditMode(conceptViewModel.getPropertyValue(MODE).equals(EDIT)); +// // setEditMode true if current conceptViewModel Mode is Edit otherwise False +// +// if (conceptViewModel.getPropertyValue(MODE).equals(CREATE)) { +// StampFormViewModelBase stampFormViewModel = propertiesController.getStampFormViewModel(); +// // if conceptViewModel say CREATE than we sub on stampFormViewModel on IS_CONFIRMED_OR_SUBMITTED +// stampFormViewModel.getProperty(IS_CONFIRMED_OR_SUBMITTED).subscribe(this::onConfirmStampFormWhenCreating); +// } else { +// // add axiom pencil is only for create mode +// // In view mode you can't add a sufficient/necc set +// addAxiomButton.setVisible(false); +// } +// }); + } + + // setup ConceptPropertiesController only for now + // later can also do timeline etc + private void setupNodes() { + + Config propertiesConfig = new Config(ConceptPropertiesController.class.getResource( + ConceptPropertiesController.CONCEPT_PROPERTIES_FXML_FILE + )).addNamedViewModel(new NamedVm("conceptViewModelNext", conceptViewModelNext)); + this.propertiesJFXNode= FXMLMvvmLoader.make(propertiesConfig); + + // Load Timeline View Panel (FXML & Controller) + FXMLLoader timelineFXMLLoader = new FXMLLoader(TimelineController.class.getResource(CONCEPT_TIMELINE_VIEW_FXML_FILE)); + try { + this.timelinePane = timelineFXMLLoader.load(); + this.timelineController = timelineFXMLLoader.getController(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + // attach properties and timeline node to slideout + addPaneToTray(timelinePane, timelineSlideoutTrayPane); + addPaneToTray(propertiesJFXNode.node(), propertiesSlideoutTrayPane); + + String styleSheet = defaultStyleSheet(); + propertiesJFXNode.node().getStylesheets().add(styleSheet); + timelinePane.getStylesheets().add(styleSheet); + } + + private void setupConceptHeader() { + propertiesToggleButton.selectedProperty().subscribe( isToggled -> { + if (isToggled != null) { + if (isToggled) { + LOG.info("toogled prop button"); + SelectedPropertyWindowKind windowKind = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND); + boolean noWindowWasPreviouslyOpen = windowKind == SelectedPropertyWindowKind.NONE || windowKind == null; + LOG.info("Current window Kind: " + windowKind); + + if (noWindowWasPreviouslyOpen) { + LOG.info("open default window"); + // open default one + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.HISTORY); + } + } + + updateDraggableNodesForPropertiesPanel(isToggled); + } + + }); + } + + private void setupTimelineBindings() { + // This will highlight with green around the pane when the user selects a date point in the timeline. + this.timelineController.onDatePointSelected((changeCoordinate) -> { + propertiesJFXNode.controller().getHistoryChangeController().highlightListItemByChangeCoordinate(changeCoordinate); + }); + // When Date points are in range (range slider) + this.timelineController.onDatePointInRange((rangeToggleOn, changeCoordinates) -> { + if (rangeToggleOn) { + propertiesJFXNode.controller().getHistoryChangeController().filterByRange(changeCoordinates); + propertiesJFXNode.controller().getHierarchyController().diffNavigationGraph(changeCoordinates); + } else { + propertiesJFXNode.controller().getHistoryChangeController().unfilterByRange(); + propertiesJFXNode.controller().getHierarchyController().diffNavigationGraph(Set.of()); + } + }); + + } + + private void setupPropertyBindings() { + SimpleObjectProperty windowKindProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND); + windowKindProp.subscribe(selectedPropertyWindowKind -> { + LOG.info("New Window Kind: " + selectedPropertyWindowKind); + switch (selectedPropertyWindowKind) { + case STAMP -> setPropertiesPanelOpen(true, true); + case MENU -> setPropertiesPanelOpen(true, true); + case NAME_MENU -> { + setPropertiesPanelOpen(true, true); + } + case NAME_FORM -> { + setPropertiesPanelOpen(true, true); + } + case HISTORY -> { + setPropertiesPanelOpen(true, true); + } + case HIERARCHY -> { + setPropertiesPanelOpen(true, true); + } + case COMMENTS -> { + setPropertiesPanelOpen(true, true); + } + case NONE -> setPropertiesPanelOpen(false, true); + case null -> setPropertiesPanelOpen(false, true); + } + }); + } + + private void setupDetailsBanner() { + setupIdenticon(); + setupStampBindings(); + } + + private void setupIdenticon() { + identiconImageView.setOnContextMenuRequested(contextMenuEvent -> { + // query all available memberships (semantics having the purpose as 'membership', and no fields) + // query current concept's membership semantic records. + // build menuItems according to 'add' or 'remove' , style to look like figma designs style classes. + // show offset to the right of the identicon + ViewCalculator viewCalculator = conceptViewModelNext.getViewProperties().calculator(); + EntityFacade currentConceptFacade = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); + List patterns = getMembershipPatterns(); + ContextMenu membershipContextMenu = new ContextMenu(); + membershipContextMenu.getStyleClass().add("kview-context-menu"); + + Comparator patternMenuComparator = (m1, m2) -> m1.getText().compareToIgnoreCase(m2.getText()); + List addedMenuItems = new ArrayList<>(); + List removedMenuItems = new ArrayList<>(); + for (PatternEntityVersion pattern : patterns) { + MenuItem menuItem = new MenuItem(); + if (isInMembershipPattern(currentConceptFacade.nid(), pattern.nid(), viewCalculator)) { + menuItem.setText("Remove from " + pattern.entity().description()); + menuItem.setOnAction(evt -> removeFromMembershipPattern(currentConceptFacade.nid(), pattern.entity(), viewCalculator)); + addedMenuItems.add(menuItem); + } else { + menuItem.setText("Add to " + pattern.entity().description()); + menuItem.setOnAction(evt -> addToMembershipPattern(currentConceptFacade, pattern.entity(), viewCalculator)); + removedMenuItems.add(menuItem); + } + } + if (!addedMenuItems.isEmpty()) { + // sort the added (able to be removed) + addedMenuItems.sort(patternMenuComparator); + membershipContextMenu.getItems().addAll(addedMenuItems); + // then add a menu line separator + if (!removedMenuItems.isEmpty()) { + membershipContextMenu.getItems().add(new SeparatorMenuItem()); + } + } + // then add the sorted removed (that can be added) + removedMenuItems.sort(patternMenuComparator); + membershipContextMenu.getItems().addAll(removedMenuItems); + + membershipContextMenu.show(identiconImageView, contextMenuEvent.getScreenX(), + contextMenuEvent.getSceneY() + identiconImageView.getFitHeight()); + }); + } + + private void setupStampBindings() { + // posibility stamp view state + // newConcept(no facade) & noValidStamp + // -> DISPLAY: BLANK | DO : waiting for stampForm to return as a valid one + // newConcept(no facade) & ValidStamp via Form + // -> DISPLAY: formValues, "uncommited" | DO : waiting for concept to be created and commited on axim creation + // on facade update ( e.g non null facade) + // -> DISPLAY: values derived from facade | DO: wait for either new facade update or update from form? + + stampViewControl.selectedProperty().subscribe(this::onStampSelectionChanged); // This needed ? + + SimpleBooleanProperty isNewConcept = conceptViewModelNext.getProperty(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + SimpleBooleanProperty hasValidStamp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + SimpleObjectProperty thisEntityProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); + + BooleanBinding shouldUpdateStampInfo = isNewConcept.and(hasValidStamp); + + + hasValidStamp.subscribe((isStamp) -> { + LOG.info("test retrigger of stamp toggle in ConceptController"); + if (isStamp) { + LOG.info("has valid stamp triggerd: " + isStamp); + + onConfirmStampFormWhenCreating(); + if (isNewConcept.getValue()) { // as long as we are in create mode we can update the stamp + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.HAS_VALID_STAMP, false); + } + + } + }); + +// shouldUpdateStampInfo.subscribe(isTimeToUpdate -> { +// LOG.info("In create mode: Created new STAMP correctly -> update stamp info"); +// if(isTimeToUpdate) { +// onConfirmStampFormWhenCreating(); +// } +// }); + + if (shouldUpdateStampInfo.getValue().equals(true)) { // if this all true directly at startup then once fire it manualy + onConfirmStampFormWhenCreating(); + } + + thisEntityProp.subscribe(conceptEntity -> { + + }); + } + + private void setupDetailsNameSemantics() { + + SimpleBooleanProperty hasValidStampProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + + // TODO: make sure that we can only change otherName or other FQN but not the primary fqn in non create Mode + // TODO2: above is wrong siince we can add semantics to uncommited because ViewProperties allow us to do so... + //addDescriptionButton.disableProperty().bind(hasValidStampProp.not()); + + // Listener when user enters a new fqn + ObservableList fqnFacades = conceptViewModelNext.getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS); + fqnFacades.subscribe( () -> { + //SimpleBooleanProperty hasValidStampProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + if (hasValidStampProp.getValue()) { + // TODO: make sure updateConceptBanner equivalent is there + updateFullyQualifiedNamesDescription(fqnFacades); + } else { + LOG.error("Stamp not valid -> Cannot update FQN description"); } + }); - conceptViewModel.getProperty(MODE).subscribe(() -> { - propertiesController.setEditMode(conceptViewModel.getPropertyValue(MODE).equals(EDIT)); + ObservableList otherNameFacades = conceptViewModelNext.getObservableList(ConceptViewModelNext.ConceptPropertyKeys.ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS); + otherNameFacades.subscribe( () -> { + //SimpleBooleanProperty hasValidStampProp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); - if (conceptViewModel.getPropertyValue(MODE).equals(CREATE)) { - StampFormViewModelBase stampFormViewModel = propertiesController.getStampFormViewModel(); - stampFormViewModel.getProperty(IS_CONFIRMED_OR_SUBMITTED).subscribe(this::onConfirmStampFormWhenCreating); + if (hasValidStampProp.getValue()) { + updateOtherNamesDescription(otherNameFacades); } else { - // add axiom pencil is only for create mode - // In view mode you can't add a sufficient/necc set - addAxiomButton.setVisible(false); + LOG.error("Stamp not valid -> Cannot update otherName description"); } }); + } + private void setupAxioms(){} + + private void onConfirmStampFormWhenCreating() { // Update StampViewControl - StampFormViewModelBase stampFormViewModel = propertiesController.getStampFormViewModel(); - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); + StampFormViewModelBase stampFormViewModel = this.propertiesJFXNode.controller().getStampFormViewModel(); + ViewCalculator viewCalculator = conceptViewModelNext.getViewProperties().calculator(); + LOG.info(stampFormViewModel.toString()); // - Status State status = stampFormViewModel.getPropertyValue(STATUS); String statusText = viewCalculator.getPreferredDescriptionTextWithFallbackOrNid(status.nid()); @@ -617,8 +840,8 @@ private boolean shouldConsumeVerticalScroll(ScrollPane scrollPane, ScrollEvent e return (atTop && deltaY > 0) || (atBottom && deltaY < 0); } - public ValidationViewModel getConceptViewModel() { - return conceptViewModel; + public ConceptViewModelNext getConceptViewModel() { + return conceptViewModelNext; } private void setUpDescriptionContextMenu(Button addDescriptionButton) { @@ -628,8 +851,10 @@ private void setUpDescriptionContextMenu(Button addDescriptionButton) { } private void onAddDescriptionButtonPressed(ActionEvent actionEvent) { - if (this.conceptViewModel.getPropertyValue(MODE).equals(CREATE) && - getConceptViewModel().getObservableList(FULLY_QUALIFIED_NAMES).isEmpty()) { + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + boolean hasNoFQNSemantics = this.conceptViewModelNext.getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS).isEmpty(); + if ( isNewConcept && + hasNoFQNSemantics) { // Show the context menu with 'Add Fully Qualified' option when it is a new concept in create mode and // there is no fully qualified name. fireContextMenuEvent(actionEvent, Side.RIGHT, 2, 0); @@ -640,22 +865,26 @@ private void onAddDescriptionButtonPressed(ActionEvent actionEvent) { } private void showAddAnotherNameUI() { - ConceptEntity currentConcept = null; - if (getConceptViewModel().getPropertyValue(CURRENT_ENTITY) instanceof EntityProxy.Concept concept) { - currentConcept = (ConceptEntity) EntityService.get().getEntity(concept.nid()).get(); - } else { - currentConcept = getConceptViewModel().getPropertyValue(CURRENT_ENTITY); - } - if (currentConcept != null) { - // in edit mode, will have a concept and public id - eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(addDescriptionButton, - // pass the publicId of the Concept - AddOtherNameToConceptEvent.ADD_DESCRIPTION, currentConcept.publicId())); // concept's publicId - } else { - // in create mode, we won't have a concept and public id yet - eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(addDescriptionButton, - AddOtherNameToConceptEvent.ADD_DESCRIPTION)); - } +// ConceptEntity currentConcept = null; +// if (this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE) instanceof EntityProxy.Concept concept) { +// LOG.info("current ConceptEntitiy via EntityProxy Service !!!"); +// currentConcept = (ConceptEntity) EntityService.get().getEntity(concept.nid()).get(); +// } else { +// LOG.info("current ConceptEntitiy read from our state !!!"); // TODO: maybe this is not correct? +// currentConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); +// } + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, null); // make sure that we create a new window + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); +// if (currentConcept != null) { +// // in edit mode, will have a concept and public id +// eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(addDescriptionButton, +// // pass the publicId of the Concept +// AddOtherNameToConceptEvent.ADD_DESCRIPTION, currentConcept.publicId())); // concept's publicId +// } else { +// // in create mode, we won't have a concept and public id yet +// eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(addDescriptionButton, +// AddOtherNameToConceptEvent.ADD_DESCRIPTION)); +// } } private ContextMenu buildMenuOptionContextMenu() { @@ -676,19 +905,21 @@ private ContextMenu buildMenuOptionContextMenu() { // if there is a fully qualified name, then do not give the option Add Fully Qualified Object[][] menuItems; + + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + boolean hasNoFQNSet = this.conceptViewModelNext.getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS).isEmpty(); // show the 'Add Fully Qualified' option when it is a new concept in create mode and there is no fully qualified name - if (this.conceptViewModel.getPropertyValue(MODE).equals(CREATE) && - getConceptViewModel().getObservableList(FULLY_QUALIFIED_NAMES).isEmpty()) { + if (isNewConcept && + hasNoFQNSet) { menuItems = new Object[][]{ {"ADD DESCRIPTION", true, new String[]{"menu-header-left-align"}, null, null}, {MenuHelper.SEPARATOR}, - {"Add Fully Qualified Name", true, null, (EventHandler) actionEvent -> - eventBus.publish(conceptTopic, new AddFullyQualifiedNameEvent(contextMenu, - AddFullyQualifiedNameEvent.ADD_FQN, conceptViewModel.getViewProperties())), + {"Add Fully Qualified Name", true, null, (EventHandler) actionEvent -> { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + } , createConceptEditDescrIcon()}, {"Add Other Name", true, null, (EventHandler) actionEvent -> { - eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(contextMenu, - AddOtherNameToConceptEvent.ADD_DESCRIPTION)); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); }, createConceptEditDescrIcon()}, {MenuHelper.SEPARATOR}, @@ -711,9 +942,9 @@ private ContextMenu buildMenuOptionContextMenu() { MenuItem menuItem = menuHelper.createMenuOption( String.valueOf(menuItemObj[NAME]), /* name */ Boolean.parseBoolean(String.valueOf(menuItemObj[ENABLED])), /* enabled */ - (String[]) menuItemObj[STYLES], /* styling */ + (String[]) menuItemObj[STYLES], /* styling */ menuItemAction, /* action when selected */ - (Node) menuItemObj[GRAPHIC] /* optional graphic */ + (Node) menuItemObj[GRAPHIC] /* optional graphic */ ); contextMenu.getItems().add(menuItem); } @@ -737,41 +968,33 @@ private void popupAddAxiomContextMenu(ActionEvent actionEvent) { @FXML private void addNecessarySet(ActionEvent actionEvent) { - conceptViewModel.setPropertyValue(AXIOM, ConceptViewModel.NECESSARY_SET); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.AXIOM, ConceptViewModelNext.NECESSARY_SET); + createConcept(); - // Attempts to write data - if (CREATE.equals(conceptViewModel.getPropertyValue(MODE))) { - boolean isWritten = conceptViewModel.createConcept(propertiesController.getStampFormViewModel()); - LOG.info("Is " + conceptViewModel + " created? " + isWritten); - if (isWritten) { - updateView(); - } - } } @FXML private void addSufficientSet(ActionEvent actionEvent) { - conceptViewModel.setPropertyValue(AXIOM, ConceptViewModel.SUFFICIENT_SET); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.AXIOM, ConceptViewModelNext.SUFFICIENT_SET); + createConcept(); + + } + private void createConcept() { + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); // Attempts to write data - if (CREATE.equals(conceptViewModel.getPropertyValue(MODE))) { - boolean isWritten = conceptViewModel.createConcept(propertiesController.getStampFormViewModel()); - LOG.info("Is " + conceptViewModel + " created? " + isWritten); + if (isNewConcept) { // TODO: is this the correct | e.g do we make sure that this does not happen in wrong state + boolean isWritten = conceptViewModelNext.createConcept(this.propertiesJFXNode.controller().getStampFormViewModel()); + LOG.info("Is " + conceptViewModelNext + " created? " + isWritten); if (isWritten) { - updateView(); + LOG.info( "yell at our overlords to reset ourself"); + //TODO: reset ourselfs + //updateView(); } } } - public void attachPropertiesViewSlideoutTray(Pane propertiesViewBorderPane, - PropertiesController propertiesController) { - this.propertiesController = propertiesController; - addPaneToTray(propertiesViewBorderPane, propertiesSlideoutTrayPane); - } - public void attachTimelineViewSlideoutTray(Pane timelineViewBorderPane) { - addPaneToTray(timelineViewBorderPane, timelineSlideoutTrayPane); - } private void addPaneToTray(Pane contentViewPane, Pane slideoutTrayPane) { double width = contentViewPane.getWidth(); contentViewPane.setLayoutX(width); @@ -795,18 +1018,13 @@ void closeConceptWindow(ActionEvent event) { // Clean up the draggable nodes removeDraggableNodes(detailsOuterBorderPane, conceptHeaderControlToolBarHbox, - propertiesController != null ? propertiesController.getPropertiesTabsPane() : null); + this.propertiesJFXNode.controller() != null ? this.propertiesJFXNode.controller().getPropertiesTabsPane() : null); if (this.onCloseConceptWindow != null) { onCloseConceptWindow.accept(this); } LOG.info("Closing & cleaning concept window: %s - %s".formatted(identifierControl.getPublicIdList(), fqnTitleText.getText())); // unsubscribe listeners - eventBus.unsubscribe(conceptTopic, EditConceptFullyQualifiedNameEvent.class, editConceptFullyQualifiedNameEventSubscriber); - eventBus.unsubscribe(conceptTopic, AddFullyQualifiedNameEvent.class, addFullyQualifiedNameEventSubscriber); - eventBus.unsubscribe(conceptTopic, EditOtherNameConceptEvent.class, editOtherNameConceptEventSubscriber); - eventBus.unsubscribe(conceptTopic, AddOtherNameToConceptEvent.class, addOtherNameToConceptEventSubscriber); - eventBus.unsubscribe(conceptTopic, ClosePropertiesPanelEvent.class, closePropertiesPanelEventSubscriber); eventBus.unsubscribe(conceptTopic, CreateConceptEvent.class, createConceptEventSubscriber); eventBus.unsubscribe(conceptTopic, EditConceptEvent.class, editConceptEventSubscriber); eventBus.unsubscribe(RULES_TOPIC, AxiomChangeEvent.class, changeSetTypeEventSubscriber); @@ -817,12 +1035,13 @@ public Pane getPropertiesSlideoutTrayPane() { } public void updateView() { - EntityFacade entityFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); - if (entityFacade != null) { // edit concept - getConceptViewModel().setPropertyValue(MODE, EDIT); - } else { // create concept - getConceptViewModel().setPropertyValue(MODE, CREATE); - } + // TODO: this should have happend on whatever called updateView +// EntityFacade entityFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); +// if (entityFacade != null) { // edit concept +// getConceptViewModel().setPropertyValue(MODE, EDIT); +// } else { // create concept +// getConceptViewModel().setPropertyValue(MODE, CREATE); +// } // Display info for top banner area updateConceptBanner(); @@ -847,18 +1066,22 @@ public void onReasonerSlideoutTray(Consumer reasonerResultsControl */ public void updateConceptBanner() { // do not update ui should be blank - if (getConceptViewModel().getPropertyValue(MODE) == CREATE) { + + // in create mode we update the ui through a callback from thew viewmodel ( e.g getting the uncommited stamp) + // and not through this updateConceptBanner + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + if (isNewConcept) { return; } - EntityFacade entityFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); - final ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); + EntityFacade entityFacade = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); + + final ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); // check to see if the latest version exists viewCalculator.latest(entityFacade).ifPresentOrElse( entityVersion -> { - // Title (FQN of concept) String conceptNameStr = viewCalculator.languageCalculator().getDescriptionTextOrNid(entityFacade.nid()); fqnTitleText.setText(conceptNameStr); @@ -903,7 +1126,7 @@ public void updateConceptBanner() { }, // else no value present () -> { - getConceptViewModel().setPropertyValue(MODE, VIEW); + //getConceptViewModel().setPropertyValue(MODE, VIEW); stampViewControl.setStatus(NO_VERSION_FOR_VIEW_TEXT); stampViewControl.setModule(NO_VERSION_FOR_VIEW_TEXT); stampViewControl.setAuthor(NO_VERSION_FOR_VIEW_TEXT); @@ -920,26 +1143,30 @@ private void updateDisplayIdentifier(ViewCalculator viewCalculator, ConceptFacad public void updateFullyQualifiedNamesDescription(List descrNameViewModels) { fullyQualifiedNameNodeListControl.getItems().clear(); - descrNameViewModels.forEach(fullyQualifedName -> { + descrNameViewModels.forEach(nameModel -> { // start adding a row - VBox fullyQualifiedNameVBox = generateDescriptionSemanticRow(fullyQualifedName); + VBox fullyQualifiedNameVBox = generateDescriptionSemanticRow(nameModel); TextFlow firstRow = (TextFlow) fullyQualifiedNameVBox.getChildren().getFirst(); - firstRow.setOnMouseClicked(event -> eventBus.publish(conceptTopic, - new EditConceptFullyQualifiedNameEvent(fullyQualifiedNameVBox, - EditConceptFullyQualifiedNameEvent.EDIT_FQN, fullyQualifedName))); + firstRow.setOnMouseClicked(event -> { + LOG.info("clicked to update fqn"); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, new UncommittedSemanticNameDescr(nameModel)); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + }); fullyQualifiedNameNodeListControl.getItems().add(fullyQualifiedNameVBox); }); } public void updateOtherNamesDescription(List descrNameViewModels) { otherNamesNodeListControl.getItems().clear(); - descrNameViewModels.forEach(otherName -> { + descrNameViewModels.forEach(nameModel -> { // start adding a row - VBox otherNameBox = generateDescriptionSemanticRow(otherName); + VBox otherNameBox = generateDescriptionSemanticRow(nameModel); TextFlow firstRow = (TextFlow) otherNameBox.getChildren().getFirst(); - firstRow.setOnMouseClicked(event -> eventBus.publish(conceptTopic, - new EditOtherNameConceptEvent(otherNameBox, - EditOtherNameConceptEvent.EDIT_OTHER_NAME, otherName))); + firstRow.setOnMouseClicked(event -> { + LOG.info("clicked to update otherName"); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, new UncommittedSemanticNameDescr(nameModel)); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + }); otherNamesNodeListControl.getItems().add(otherNameBox); }); } @@ -949,13 +1176,17 @@ public void updateOtherNamesDescription(List descrNameViewModels) { */ public void updateConceptDescription() { // do not update ui should be blank - if (getConceptViewModel().getPropertyValue(MODE) == CREATE) { + + //TODO: while we are updating the stamp via callbacks in new Concepts we do it differently for desciptions.. + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + if (isNewConcept) { return; } - final ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); - EntityFacade entityFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); + final ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); + + EntityFacade entityFacade = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); viewCalculator.latest(entityFacade).ifPresentOrElse( _ -> { @@ -969,6 +1200,7 @@ public void updateConceptDescription() { int descriptionTypeIndex = patternEntityVersion.indexForMeaning(DESCRIPTION_TYPE.nid()); descriptionSemanticsMap.forEach((semanticEntityVersion, fieldDescriptions) -> { + EntityFacade fieldTypeValue = (EntityFacade) semanticEntityVersion.fieldValues().get(descriptionTypeIndex); boolean isFQN = FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE.nid() == fieldTypeValue.nid(); boolean isOtherName = REGULAR_NAME_DESCRIPTION_TYPE.nid() == fieldTypeValue.nid(); @@ -979,9 +1211,15 @@ public void updateConceptDescription() { VBox fullyQualifiedNameBox = generateDescriptionSemanticRow(semanticEntityVersion, fieldDescriptions); PublicId fullyQuallifiedNamePublicId = (PublicId) fullyQualifiedNameBox.getChildren().getFirst().getUserData(); TextFlow row = (TextFlow) fullyQualifiedNameBox.getChildren().getFirst(); - row.setOnMouseClicked(event -> eventBus.publish(conceptTopic, - new EditConceptFullyQualifiedNameEvent(fullyQualifiedNameBox, - EditConceptFullyQualifiedNameEvent.EDIT_FQN, fullyQuallifiedNamePublicId))); + row.setOnMouseClicked(event -> { + LOG.info("clicked edit FQN Name = " + semanticEntityVersion + " " + fieldDescriptions); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, new SemanticPublicId(fullyQuallifiedNamePublicId)); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); +// // TODO: remove associated event +// eventBus.publish(conceptTopic, +// new EditConceptFullyQualifiedNameEvent(fullyQualifiedNameBox, +// EditConceptFullyQualifiedNameEvent.EDIT_FQN, fullyQuallifiedNamePublicId)); + }); fullyQualifiedNameNodeListControl.getItems().add(fullyQualifiedNameBox); LOG.debug("FQN Name = " + semanticEntityVersion + " " + fieldDescriptions); } else if (isOtherName) { @@ -989,9 +1227,15 @@ public void updateConceptDescription() { VBox otherNameBox = generateDescriptionSemanticRow(semanticEntityVersion, fieldDescriptions); PublicId otherNamePublicId = (PublicId) otherNameBox.getChildren().getFirst().getUserData(); TextFlow firstRow = (TextFlow) otherNameBox.getChildren().getFirst(); - firstRow.setOnMouseClicked(event -> eventBus.publish(conceptTopic, - new EditOtherNameConceptEvent(otherNameBox, - EditOtherNameConceptEvent.EDIT_OTHER_NAME, otherNamePublicId))); + firstRow.setOnMouseClicked(event -> { + LOG.info("edit Other Names = " + semanticEntityVersion + " " + fieldDescriptions); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, new SemanticPublicId(otherNamePublicId)); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); +// // TODO: remove associated event +// eventBus.publish(conceptTopic, +// new EditOtherNameConceptEvent(otherNameBox, +// EditOtherNameConceptEvent.EDIT_OTHER_NAME, otherNamePublicId)); + }); otherNamesNodeListControl.getItems().add(otherNameBox); LOG.debug("Other Names = " + semanticEntityVersion + " " + fieldDescriptions); @@ -1005,17 +1249,31 @@ public void updateConceptDescription() { final int otherNamesCount = otherNamesNodeListControl.getItems().size(); otherNamesHeaderText.setText(otherNamesCount > 0 ? String.format("OTHER NAMES (%d):", otherNamesCount) : "OTHER NAMES:"); + + LOG.info("set exampend stuff in update Concept description"); + //otherNamesNodeListControl.setExpanded(true); + LOG.info("Layout bounds"); + LOG.info(otherNamesNodeListControl.getLayoutBounds().toString()); + LOG.info(" bounds in parent"); + LOG.info(otherNamesNodeListControl.getBoundsInParent().toString()); + LOG.info(" bounds in local"); + LOG.info(otherNamesNodeListControl.getBoundsInLocal().toString()); + + + //otherNamesNodeListControl.setExpanded(false); + //otherNamesNodeListControl.setExpanded(true); }, // else no value present () -> { - getConceptViewModel().setPropertyValue(MODE, VIEW); - List fqns = getConceptViewModel().getValue(FULLY_QUALIFIED_NAMES); + LOG.error(" try to populate description semantics while not having a valid concept entity and not being in create mode"); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT, false); + List fqns = this.conceptViewModelNext.getList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS); if (fqns != null && !fqns.isEmpty()) { VBox fqnVBox = new VBox(new Label(NO_VERSION_FOR_VIEW_TEXT)); fullyQualifiedNameNodeListControl.getItems().clear(); fullyQualifiedNameNodeListControl.getItems().add(fqnVBox); } - List ots = getConceptViewModel().getValue(OTHER_NAMES); + List ots = this.conceptViewModelNext.getList(ConceptPropertyKeys.ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS); if (ots != null && !ots.isEmpty()) { VBox otherNameVBox = new VBox(new Label(NO_VERSION_FOR_VIEW_TEXT)); otherNamesNodeListControl.getItems().clear(); @@ -1033,118 +1291,83 @@ public void updateConceptDescription() { * @return */ private VBox generateDescriptionSemanticRow(SemanticEntityVersion semanticEntityVersion, List fieldDescriptions) { - VBox textFlowsBox = new VBox(); + ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); //* + + boolean hasFieldDescription = !fieldDescriptions.isEmpty(); + String nameDescText = getFieldValueByMeaning(semanticEntityVersion, TinkarTerm.TEXT_FOR_DESCRIPTION); + + PublicId semanticPubId = semanticEntityVersion.publicId(); //* + boolean isACommitedSemantic = semanticPubId != null; String descrSemanticStr = String.join(", ", fieldDescriptions); + //---- - // create textflow to hold regular name label - TextFlow row1 = new TextFlow(); - String otherNameDescText = getFieldValueByMeaning(semanticEntityVersion, TinkarTerm.TEXT_FOR_DESCRIPTION); - Text otherNameLabel = new Text(otherNameDescText); - otherNameLabel.getStyleClass().add("descr-concept-name"); + return updateThing(viewCalculator, semanticPubId, descrSemanticStr, nameDescText); + } - Text semanticDescrText = new Text(); - if (!fieldDescriptions.isEmpty()) { - semanticDescrText.setText(" (%s)".formatted(descrSemanticStr)); - semanticDescrText.getStyleClass().add("descr-concept-name"); + // This method is usefull when we are adding new semantics descr and want to update + // the shown display while the parent concept itself is a) in create mode && not commited + // otherwise we can always get the "latest" via DB + private VBox generateDescriptionSemanticRow(DescrName nameModel) { + ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); //* + ConceptEntity caseSigConcept = nameModel.getCaseSignificance(); //* + String casSigText = viewCalculator.languageCalculator().getDescriptionTextOrNid(caseSigConcept.nid()); //* + ConceptEntity langConcept = nameModel.getLanguage(); //* + String langText = viewCalculator.languageCalculator().getDescriptionTextOrNid(langConcept.nid()); //* + boolean hasFieldDescription = !casSigText.isEmpty() && !langText.isEmpty(); + // TODO: need to retrieve the description Semantic's Text field (latest version text). + PublicId semanticPubId = nameModel.getSemanticPublicId(); //* + boolean isACommitedSemantic = semanticPubId != null; + String nameDescText; + // the semanticPublicId is null in CREATE mode, so use the nameText that was entered + // instead of the semanticPublicId field value + if (isACommitedSemantic) { + int nid = EntityService.get().nidForPublicId(semanticPubId); + Latest regularDescriptionTextversion = viewCalculator.latest(nid); + nameDescText = regularDescriptionTextversion.get().fieldValues().get(1).toString(); } else { - semanticDescrText.setText(""); + nameDescText = nameModel.getNameText(); } - // add the other name label and description semantic label - row1.getStyleClass().add("descr-semantic-container"); - // store the public id of this semantic entity version - // so that when clicked the event bus can pass it to the form - // and the form can populate the data from the publicId - row1.setUserData(semanticEntityVersion.publicId()); - row1.getChildren().addAll(otherNameLabel, semanticDescrText); + LOG.info("NameLabel : "+ nameDescText); + String descrSemanticStr = "%s, %s".formatted(casSigText, langText); //*- - TextFlow row2 = new TextFlow(); - Text dateAddedLabel = new Text("Date Added: "); - dateAddedLabel.getStyleClass().add("grey8-12pt-bold"); + //----- - if (semanticEntityVersion.publicId() != null) { - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); - Latest semanticVersionLatest = viewCalculator.latest(Entity.nid(semanticEntityVersion.publicId())); - semanticVersionLatest.ifPresent(entityVersion -> { - long rawTime = entityVersion.time(); - String dateText = null; - if (rawTime == PREMUNDANE_TIME) { - dateText = PREMUNDANE; - } else { - Locale userLocale = Locale.getDefault(); - LocalDate localDate = Instant.ofEpochMilli(rawTime).atZone(ZoneId.systemDefault()).toLocalDate(); - DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(userLocale); - dateText = formatter.format(localDate); - } - - Text dateLabel = new Text(dateText); - dateLabel.getStyleClass().add("grey8-12pt-bold"); - - Region spacer = new Region(); - spacer.setMinWidth(10); - - Hyperlink attachmentHyperlink = createActionLink(IconsHelper.createIcon(ATTACHMENT)); - Hyperlink commentsHyperlink = createActionLink(IconsHelper.createIcon(COMMENTS)); + return updateThing(viewCalculator, semanticPubId, descrSemanticStr, nameDescText); - // Add the date info and additional hyperlinks - row2.getChildren().addAll(dateAddedLabel, dateLabel, spacer, attachmentHyperlink, commentsHyperlink); - }); - } - - textFlowsBox.getChildren().addAll(row1, row2); - return textFlowsBox; } - private VBox generateDescriptionSemanticRow(DescrName otherName) { - VBox textFlowsBox = new VBox(); - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); - ConceptEntity caseSigConcept = otherName.getCaseSignificance(); - String casSigText = viewCalculator.languageCalculator().getDescriptionTextOrNid(caseSigConcept.nid()); - ConceptEntity langConcept = otherName.getLanguage(); + private VBox updateThing(ViewCalculator viewCalculator, PublicId semanticPubId,String descrSemanticStr, String nameDescText) { + boolean isACommitedSemantic = semanticPubId != null; - String langText = viewCalculator.languageCalculator().getDescriptionTextOrNid(langConcept.nid()); - - String descrSemanticStr = "%s, %s".formatted(casSigText, langText); + VBox textFlowsBox = new VBox(); // create textflow to hold regular name label TextFlow row1 = new TextFlow(); - // TODO: need to retrieve the description Semantic's Text field (latest version text). - - PublicId semanticPid = otherName.getSemanticPublicId(); - Text otherNameLabel; + Text nameLabel = new Text(nameDescText); + nameLabel.getStyleClass().add("descr-concept-name"); - // the semanticPublicId is null in CREATE mode, so use the nameText that was entered - // instead of the semanticPublicId field value - if (semanticPid != null) { - int nid = EntityService.get().nidForPublicId(semanticPid); - Latest regularDescriptionTextversion = viewCalculator.latest(nid); - otherNameLabel = new Text(regularDescriptionTextversion.get().fieldValues().get(1).toString()); + Text semanticDescrText = new Text(); + if (!descrSemanticStr.isEmpty() || !descrSemanticStr.isBlank()) { + semanticDescrText.setText(" (%s)".formatted(descrSemanticStr)); + semanticDescrText.getStyleClass().add("descr-concept-name"); } else { - otherNameLabel = new Text(otherName.getNameText()); + semanticDescrText.setText(""); } - LOG.info("otherNameLabel : "+otherNameLabel); - - otherNameLabel.getStyleClass().add("descr-concept-name"); - - Text semanticDescrText = new Text(); - semanticDescrText.setText(" (%s)".formatted(descrSemanticStr)); - semanticDescrText.getStyleClass().add("descr-concept-name"); - // add the other name label and description semantic label row1.getStyleClass().add("descr-semantic-container"); // store the public id of this semantic entity version // so that when clicked the event bus can pass it to the form // and the form can populate the data from the publicId -// this.otherNamePublicId = semanticEntityVersion.publicId(); - - row1.getChildren().addAll(otherNameLabel, semanticDescrText); + row1.setUserData(semanticPubId); + row1.getChildren().addAll(nameLabel, semanticDescrText); TextFlow row2 = new TextFlow(); Text dateAddedLabel = new Text("Date Added: "); dateAddedLabel.getStyleClass().add("grey8-12pt-bold"); - if (otherName.getSemanticPublicId() != null) { - Latest semanticVersionLatest = viewCalculator.latest(Entity.nid(otherName.getSemanticPublicId())); + if (isACommitedSemantic) { + Latest semanticVersionLatest = viewCalculator.latest(Entity.nid(semanticPubId)); semanticVersionLatest.ifPresent(entityVersion -> { long rawTime = entityVersion.time(); String dateText = null; @@ -1170,6 +1393,7 @@ private VBox generateDescriptionSemanticRow(DescrName otherName) { row2.getChildren().addAll(dateAddedLabel, dateLabel, spacer, attachmentHyperlink, commentsHyperlink); }); } + textFlowsBox.getChildren().addAll(row1, row2); return textFlowsBox; } @@ -1209,7 +1433,7 @@ private Map> latestDescriptionSemantics(Enti // TODO: This should rely on the view calculator from the parent view properties. Below will always get the actual latest semantic version // ViewCalculator viewCalculator = getViewProperties().calculator(); /* after import this is not getting latest */ - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); /* returns committed latest from db */ + ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); /* returns committed latest from db */ viewCalculator.getDescriptionsForComponent(conceptFacade).stream() .filter(semanticEntity -> { // TODO FIXME - the latest() methods should be relative to the @@ -1217,7 +1441,7 @@ private Map> latestDescriptionSemantics(Enti // This will always return the latest record from the database not the // latest from the view coordinate position data time range. - Latest semanticEntityVersionLatest = conceptViewModel.getViewProperties().calculator().latest(semanticEntity.nid()); + Latest semanticEntityVersionLatest = this.conceptViewModelNext.getViewProperties().calculator().latest(semanticEntity.nid()); if (semanticEntityVersionLatest.isAbsent()) { return false; // No version found } @@ -1244,7 +1468,7 @@ private Map> latestDescriptionSemantics(Enti // This will always return the latest record from the database not the // latest from the view coordinate position data time range. - Latest semanticEntityVersionLatest = conceptViewModel.getViewProperties().calculator().latest(semanticEntity.nid()); + Latest semanticEntityVersionLatest = this.conceptViewModelNext.getViewProperties().calculator().latest(semanticEntity.nid()); if(semanticEntityVersionLatest.isAbsent()) { return; } @@ -1297,29 +1521,30 @@ private static ImmutableList fields(SemanticEntityVersion seman private void updateAxioms() { // do not update ui should be blank - if (getConceptViewModel().getPropertyValue(MODE) == CREATE) { + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + if (isNewConcept) { return; } // clear Axioms areas - ViewCalculator viewCalculator = conceptViewModel.getViewProperties().calculator(); - EntityFacade entityFacade = conceptViewModel.getPropertyValue(CURRENT_ENTITY); + ViewCalculator viewCalculator = this.conceptViewModelNext.getViewProperties().calculator(); + EntityFacade entityFacade = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); viewCalculator.latest(entityFacade).ifPresentOrElse( entityVersion -> { // Create a SheetItem (AXIOM inferred semantic version) // TODO Should this be reused instead of instanciating a new one everytime? - KometPropertySheet inferredPropertySheet = new KometPropertySheet(conceptViewModel.getViewProperties(), true); + KometPropertySheet inferredPropertySheet = new KometPropertySheet(this.conceptViewModelNext.getViewProperties(), true); Latest inferredSemanticVersion = viewCalculator.getInferredAxiomSemanticForEntity(entityFacade.nid()); - makeSheetItem(conceptViewModel.getViewProperties(), inferredPropertySheet, inferredSemanticVersion); + makeSheetItem(this.conceptViewModelNext.getViewProperties(), inferredPropertySheet, inferredSemanticVersion); inferredAxiomPane.setCenter(inferredPropertySheet); // Create a SheetItem (AXIOM stated semantic version) - KometPropertySheet statedPropertySheet = new KometPropertySheet(conceptViewModel.getViewProperties(), true); + KometPropertySheet statedPropertySheet = new KometPropertySheet(this.conceptViewModelNext.getViewProperties(), true); Latest statedSemanticVersion = viewCalculator.getStatedAxiomSemanticForEntity(entityFacade.nid()); - makeSheetItem(conceptViewModel.getViewProperties(), statedPropertySheet, statedSemanticVersion); + makeSheetItem(this.conceptViewModelNext.getViewProperties(), statedPropertySheet, statedSemanticVersion); statedAxiomPane.setCenter(statedPropertySheet); //TODO discuss the blue theme color related to AXIOMs @@ -1339,11 +1564,11 @@ private void makeSheetItem(ViewProperties viewProperties, KometPropertySheet propertySheet, Latest semanticVersion) { semanticVersion.ifPresent(semanticEntityVersion -> { - Latest statedPatternVersion = conceptViewModel.getViewProperties().calculator().latestPatternEntityVersion(semanticEntityVersion.pattern()); - ImmutableList fields = fields(semanticEntityVersion, statedPatternVersion.get(), conceptViewModel.getViewProperties().calculator()); + Latest statedPatternVersion = this.conceptViewModelNext.getViewProperties().calculator().latestPatternEntityVersion(semanticEntityVersion.pattern()); + ImmutableList fields = fields(semanticEntityVersion, statedPatternVersion.get(), this.conceptViewModelNext.getViewProperties().calculator()); fields.forEach(field -> // create a row as a label: editor. For Axioms we hide the left labels. - propertySheet.getItems().add(SheetItem.make(field, semanticEntityVersion, conceptViewModel.getViewProperties()))); + propertySheet.getItems().add(SheetItem.make(field, semanticEntityVersion, this.conceptViewModelNext.getViewProperties()))); }); } @@ -1385,15 +1610,23 @@ private void setStampSelectedSilently(boolean selected) { } private void onStampSelectionChanged() { + LOG.info("StampSelection changed called"); + + + + if (isUpdatingStampSelection) { return; } if (stampViewControl.isSelected()) { - if (CREATE.equals(conceptViewModel.getPropertyValue(MODE))) { + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + if (isNewConcept) { eventBus.publish(conceptTopic, new StampEvent(stampViewControl, StampEvent.CREATE_STAMP)); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.STAMP); } else { eventBus.publish(conceptTopic, new StampEvent(stampViewControl, StampEvent.ADD_STAMP)); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.STAMP); } if (!propertiesToggleButton.isSelected()) { @@ -1401,6 +1634,7 @@ private void onStampSelectionChanged() { } } else { eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(stampViewControl, CLOSE_PROPERTIES)); + this.conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NONE); } } @@ -1414,14 +1648,23 @@ private void openPropertiesPanel(ActionEvent event) { updateDraggableNodesForPropertiesPanel(true); - if (CREATE.equals(conceptViewModel.getPropertyValue(MODE)) && !stampViewControl.isSelected()) { + boolean isNewConcept = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + boolean hasValidStamp = this.conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.HAS_VALID_STAMP); + + if (isNewConcept) { // show the Add FQN - eventBus.publish(conceptTopic, new AddFullyQualifiedNameEvent(propertyToggle, - AddFullyQualifiedNameEvent.ADD_FQN, conceptViewModel.getViewProperties())); - } else if (EDIT.equals(conceptViewModel.getPropertyValue(MODE))){ + + if (hasValidStamp) { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + + } else { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.STAMP); + } + + } else { // show the button form - eventBus.publish(conceptTopic, new OpenPropertiesPanelEvent(propertyToggle, - OpenPropertiesPanelEvent.OPEN_PROPERTIES_PANEL, fqnPublicId, fqnTitleText.getText())); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.MENU); + } } else { LOG.info("Close Properties slideout"); @@ -1444,13 +1687,13 @@ private void openPropertiesPanel(ActionEvent event) { * @param isOpen {@code true} to add draggable nodes, {@code false} to remove them */ private void updateDraggableNodesForPropertiesPanel(boolean isOpen) { - if (propertiesController != null && propertiesController.getPropertiesTabsPane() != null) { + if (this.propertiesJFXNode.controller() != null && this.propertiesJFXNode.controller().getPropertiesTabsPane() != null) { if (isOpen) { - addDraggableNodes(detailsOuterBorderPane, propertiesController.getPropertiesTabsPane()); - LOG.debug("Added properties nodes as draggable"); + addDraggableNodes(detailsOuterBorderPane, this.propertiesJFXNode.controller().getPropertiesTabsPane()); + LOG.info("Added properties nodes as draggable"); } else { - removeDraggableNodes(detailsOuterBorderPane, propertiesController.getPropertiesTabsPane()); - LOG.debug("Removed properties nodes from draggable"); + removeDraggableNodes(detailsOuterBorderPane, this.propertiesJFXNode.controller().getPropertiesTabsPane()); + LOG.info("Removed properties nodes from draggable"); } } } @@ -1507,7 +1750,7 @@ private void showChangeViewCoordinateMenu(ActionEvent actionEvent) { * generate the classic Komet coordinate menu */ public void setUpEditCoordinateMenu() { - this.viewMenuModel = new ViewMenuModel(conceptViewModel.getViewProperties(), coordinatesMenuButton, "DetailsController"); + this.viewMenuModel = new ViewMenuModel(this.conceptViewModelNext.getViewProperties(), coordinatesMenuButton, "DetailsController"); } private DateTimeFormatter dateFormatter(String formatString) { @@ -1519,7 +1762,7 @@ private DateTimeFormatter dateFormatter(String formatString) { private int getFieldIndexByMeaning(SemanticEntityVersion entityVersion, EntityFacade ...meaning) { PatternEntity patternEntity = entityVersion.entity().pattern(); - PatternEntityVersion patternEntityVersion = conceptViewModel.getViewProperties().calculator().latest(patternEntity).get(); + PatternEntityVersion patternEntityVersion = this.conceptViewModelNext.getViewProperties().calculator().latest(patternEntity).get(); int index = -1; if (meaning != null && meaning.length > 0){ for (int i=0; i < meaning.length; i++){ @@ -1542,7 +1785,7 @@ private T getFieldValueByMeaning(SemanticEntityVersion entityVersion, Entity private T getFieldValueByPurpose(SemanticEntityVersion entityVersion, EntityFacade ...purpose) { PatternEntity patternEntity = entityVersion.entity().pattern(); - PatternEntityVersion patternEntityVersion = conceptViewModel.getViewProperties().calculator().latest(patternEntity).get(); + PatternEntityVersion patternEntityVersion = this.conceptViewModelNext.getViewProperties().calculator().latest(patternEntity).get(); int index = -1; if (purpose != null && purpose.length > 0){ for (int i=0; i < purpose.length; i++){ @@ -1592,4 +1835,22 @@ public void setPropertiesPanelOpen(boolean isOpen) { updateDraggableNodesForPropertiesPanel(isOpen); } + + private void setPropertiesPanelOpen(boolean isOpen, boolean animated) { + + // if we are alredy in the state we do not need to do it again + if (propertiesToggleButton.isSelected() == isOpen) { + return; + } + + propertiesToggleButton.setSelected(isOpen); + + if (isOpen) { + SlideOutTrayHelper.slideOut(propertiesSlideoutTrayPane, detailsOuterBorderPane, animated); + } else { + SlideOutTrayHelper.slideIn(propertiesSlideoutTrayPane, detailsOuterBorderPane, animated); + } + + updateDraggableNodesForPropertiesPanel(isOpen); + } } diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptNode.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptNode.java index b4bdd10b20..927e811fe5 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptNode.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptNode.java @@ -15,17 +15,8 @@ */ package dev.ikm.komet.kview.mvvm.view.concept; -import static dev.ikm.komet.framework.activity.ActivityStreamOption.PUBLISH; -import static dev.ikm.komet.framework.activity.ActivityStreamOption.SYNCHRONIZE; -import static dev.ikm.komet.kview.fxutils.CssHelper.defaultStyleSheet; -import static dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModel.CURRENT_ENTITY; -import static dev.ikm.komet.kview.mvvm.viewmodel.FormViewModel.CURRENT_JOURNAL_WINDOW_TOPIC; -import static dev.ikm.komet.kview.mvvm.viewmodel.FormViewModel.VIEW_PROPERTIES; import dev.ikm.komet.framework.ExplorationNodeAbstract; -import dev.ikm.komet.framework.TopPanelFactory; -import dev.ikm.komet.framework.controls.EntityLabelWithDragAndDrop; import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.mvvm.view.properties.PropertiesController; import dev.ikm.komet.kview.mvvm.view.timeline.TimelineController; import dev.ikm.komet.preferences.KometPreferences; import dev.ikm.tinkar.common.flow.FlowSubscriber; @@ -38,15 +29,11 @@ import javafx.fxml.FXMLLoader; import javafx.scene.Node; import javafx.scene.layout.BorderPane; -import org.carlfx.cognitive.loader.Config; -import org.carlfx.cognitive.loader.FXMLMvvmLoader; -import org.carlfx.cognitive.loader.JFXNode; +import javafx.scene.layout.Pane; import org.eclipse.collections.api.list.ImmutableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.Set; import java.util.UUID; public class ConceptNode extends ExplorationNodeAbstract { @@ -55,17 +42,13 @@ public class ConceptNode extends ExplorationNodeAbstract { protected final SimpleObjectProperty entityFocusProperty = new SimpleObjectProperty<>(); protected FlowSubscriber invalidationSubscriber; protected ChangeListener entityFocusChangeListener; - protected static final String CONCEPT_DETAILS_VIEW_FXML_FILE = "concept-details.fxml"; protected static final String STYLE_ID = "kview-details-node"; protected static final String TITLE = "Concept Details"; - private BorderPane conceptDetailsViewBorderPane; - private ConceptController conceptDetailsViewController; /////// Properties slide out ////////////////////////////// - protected static final String CONCEPT_PROPERTIES_VIEW_FXML_FILE = "properties.fxml"; - private BorderPane propertiesViewBorderPane; - private PropertiesController propertiesViewController; + + private ConceptPropertiesController propertiesViewController; ////// Timeline (Time travel) control ////////////////////// protected static final String CONCEPT_TIMELINE_VIEW_FXML_FILE = "timeline.fxml"; @@ -79,7 +62,7 @@ public ConceptNode(ViewProperties viewProperties, KometPreferences nodePreferenc public ConceptNode(ViewProperties viewProperties, KometPreferences nodePreferences, boolean displayOnJournalView) { super(viewProperties, nodePreferences); init(displayOnJournalView); - registerListeners(viewProperties); + //registerListeners(viewProperties); revertPreferences(); } @@ -87,160 +70,18 @@ public ConceptNode(ViewProperties viewProperties, KometPreferences nodePreferenc * Initialization view panel(fxml) and it's view. */ private void init(boolean displayOnJournalView) { - try { - // Let's grab what's inside the properties. Should be the journal window's event topic. - // This details concept window can message events to the current journal window. E.g. progress popup window. - UUID journalWindowTopic = nodePreferences().getUuid(PreferenceKey.CURRENT_JOURNAL_WINDOW_TOPIC).get(); - - // create a unique topic for each concept detail instance - UUID conceptTopic = UUID.randomUUID(); - - // Load Concept Details View Panel (FXML & Controller) - // 1) inside fxml - apply(file, ...view models) - // 2) not in fxml view class - apply(file, view, ...view models) - // 3) not in fxml view instance - apply(file, view instance, ...view models) - Config config = new Config(getClass().getResource(CONCEPT_DETAILS_VIEW_FXML_FILE)) - .controller(new ConceptController(conceptTopic)) - .updateViewModel("conceptViewModel", viewModel -> - viewModel.setPropertyValue(VIEW_PROPERTIES, viewProperties) - .setPropertyValue(CURRENT_JOURNAL_WINDOW_TOPIC, journalWindowTopic)); - JFXNode jfxNode = FXMLMvvmLoader.make(config); - - this.conceptDetailsViewBorderPane = jfxNode.node(); - this.conceptDetailsViewController = jfxNode.controller(); - - // Programmatically change CSS Theme - this.conceptDetailsViewBorderPane.getStylesheets().clear(); - String styleSheet = defaultStyleSheet(); - this.conceptDetailsViewBorderPane.getStylesheets().add(styleSheet); - - if (!displayOnJournalView) { - - // Add the menu drop down for coordinates & activity stream options with Blue Title of concept - Node topPanel = TopPanelFactory.make( - viewProperties, - entityFocusProperty, - activityStreamKeyProperty, - optionForActivityStreamKeyProperty, - false); - this.conceptDetailsViewBorderPane.setTop(topPanel); - } - - // Load Concept Properties View Panel (FXML & Controller) - FXMLLoader propsFXMLLoader = new FXMLLoader(PropertiesController.class.getResource(CONCEPT_PROPERTIES_VIEW_FXML_FILE)); - propsFXMLLoader.setController(new PropertiesController(conceptTopic)); - this.propertiesViewBorderPane = propsFXMLLoader.load(); - this.propertiesViewController = propsFXMLLoader.getController(); - // style the same as the details view - this.propertiesViewBorderPane.getStylesheets().add(styleSheet); - this.propertiesViewController.updateModel(viewProperties, null); - - conceptDetailsViewController.attachPropertiesViewSlideoutTray(this.propertiesViewBorderPane, this.propertiesViewController); - - // Load Timeline View Panel (FXML & Controller) - FXMLLoader timelineFXMLLoader = new FXMLLoader(TimelineController.class.getResource(CONCEPT_TIMELINE_VIEW_FXML_FILE)); - this.timelineViewBorderPane = timelineFXMLLoader.load(); - this.timelineViewController = timelineFXMLLoader.getController(); - - // This will highlight with green around the pane when the user selects a date point in the timeline. - timelineViewController.onDatePointSelected((changeCoordinate) ->{ - propertiesViewController.getHistoryChangeController().highlightListItemByChangeCoordinate(changeCoordinate); - }); - // When Date points are in range (range slider) - timelineViewController.onDatePointInRange((rangeToggleOn, changeCoordinates) -> { - if (rangeToggleOn) { - propertiesViewController.getHistoryChangeController().filterByRange(changeCoordinates); - propertiesViewController.getHierarchyController().diffNavigationGraph(changeCoordinates); - } else { - propertiesViewController.getHistoryChangeController().unfilterByRange(); - propertiesViewController.getHierarchyController().diffNavigationGraph(Set.of()); - } - }); - - // style the same as the details view - this.timelineViewBorderPane.getStylesheets().add(styleSheet); - - // setup view and view into details view - conceptDetailsViewController.attachTimelineViewSlideoutTray(this.timelineViewBorderPane); - - } catch (IOException e) { - throw new RuntimeException(e); - } + // Let's grab what's inside the properties. Should be the journal window's event topic. + // This details concept window can message events to the current journal window. E.g. progress popup window. + UUID journalWindowTopic = nodePreferences().getUuid(PreferenceKey.CURRENT_JOURNAL_WINDOW_TOPIC).get(); } - /** - * Wireup listeners(handler code) that will respond on change. E.g. The entityFocusProperty changes when a user selects a concept (in a Navigator tree view). - * @param viewProperties - */ - private void registerListeners(ViewProperties viewProperties) { - // remove later when closing - this.entityFocusChangeListener = (observable, oldEntityFacade, newEntityFacade) -> { - if (newEntityFacade != null) { - titleProperty.set(viewProperties.calculator().getPreferredDescriptionTextWithFallbackOrNid(newEntityFacade)); - toolTipTextProperty.set(viewProperties.calculator().getFullyQualifiedDescriptionTextWithFallbackOrNid(newEntityFacade)); - - // Populate Detail View - if (getConceptDetailsViewController() != null) { - getConceptDetailsViewController() - .getConceptViewModel() - .setPropertyValue(CURRENT_ENTITY, newEntityFacade); - getConceptDetailsViewController().updateView(); - } - - // Populate Properties View - if (getPropertiesViewController() != null) { - getPropertiesViewController().updateModel(viewProperties, newEntityFacade); - getPropertiesViewController().updateView(); - } - - // Populate Timeline View - if (getTimelineViewController() != null) { - getTimelineViewController().resetConfigPathAndModules(); - getTimelineViewController().updateModel(viewProperties, newEntityFacade); - getTimelineViewController().updateView(); - } - - } else { - // Show a blank view (nothing selected) - titleProperty.set(EntityLabelWithDragAndDrop.EMPTY_TEXT); - toolTipTextProperty.set(EntityLabelWithDragAndDrop.EMPTY_TEXT); - getConceptDetailsViewController().clearView(); - getPropertiesViewController().clearView(); - getPropertiesViewController().updateModel(viewProperties, newEntityFacade); - } - - }; - - // When a new entity is selected populate the view. An entity has been selected upstream (activity stream) - this.entityFocusProperty.addListener(this.entityFocusChangeListener); - - // If database updates the underlying entity, this will do a force update of the UI. - this.invalidationSubscriber = new FlowSubscriber<>(nid -> { - if (entityFocusProperty.get() != null && entityFocusProperty.get().nid() == nid) { - // component has changed, need to update. - Platform.runLater(() -> entityFocusProperty.set(null)); - Platform.runLater(() -> entityFocusProperty.set(Entity.provider().getEntityFast(nid))); - } - }); - - // Register to the Entity Service - Entity.provider().addSubscriberWithWeakReference(this.invalidationSubscriber); - } protected void revertDetailsPreferences() { } - /** - * Returns the associated view to update the UI. - * @return DetailsController The attached view to the Details view (fxml) - */ - public ConceptController getConceptDetailsViewController() { - return conceptDetailsViewController; - } - - public PropertiesController getPropertiesViewController() { + public ConceptPropertiesController getPropertiesViewController() { return propertiesViewController; } @@ -255,12 +96,14 @@ public String getDefaultTitle() { @Override public void handleActivity(ImmutableList entities) { + LOG.info("handle activiy called ...."); if (entities.isEmpty()) { entityFocusProperty.set(null); } else { EntityFacade entityFacade = entities.get(0); // Only display Concept Details. if (entityFacade instanceof ConceptFacade) { + LOG.info( "GOT OUR FACADE THROUGH handle ACTIVITY ??"); entityFocusProperty.set(entityFacade); } else { entityFocusProperty.set(null); @@ -271,6 +114,7 @@ public void handleActivity(ImmutableList entities) { @Override public final void revertAdditionalPreferences() { if (nodePreferences.hasKey(DetailNodeKey.ENTITY_FOCUS)) { + LOG.info("reverting our entity back through OLD preference system"); nodePreferences.getEntity(DetailNodeKey.ENTITY_FOCUS).ifPresentOrElse(entityFacade -> entityFocusProperty.set(entityFacade), () -> entityFocusProperty.set(null)); } @@ -284,6 +128,7 @@ public String getStyleId() { @Override protected void saveAdditionalPreferences() { + LOG.info("Save current entity through old preference system"); if (entityFocusProperty.get() != null) { nodePreferences.putEntity(DetailNodeKey.ENTITY_FOCUS, entityFocusProperty.get()); } else { @@ -297,9 +142,10 @@ protected void saveDetailsPreferences() { } + @Override public Node getNode() { - return this.conceptDetailsViewBorderPane; + return new Pane(); } @Override diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesController.java new file mode 100644 index 0000000000..3ada3d084e --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesController.java @@ -0,0 +1,379 @@ +package dev.ikm.komet.kview.mvvm.view.concept; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.mvvm.model.DescrName; +import dev.ikm.komet.kview.mvvm.view.common.StampFormController; +import dev.ikm.komet.kview.mvvm.view.properties.*; +import dev.ikm.komet.kview.mvvm.viewmodel.*; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext.*; +import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampAddSubmitFormViewModel; +import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampCreateFormViewModel; +import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase; +import dev.ikm.tinkar.common.id.PublicId; +import dev.ikm.tinkar.terms.EntityFacade; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import org.carlfx.cognitive.loader.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.UUID; + +import static dev.ikm.komet.kview.fxutils.CssHelper.genText; +import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.IS_CONFIRMED_OR_SUBMITTED; +import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.IS_STAMP_VALUES_THE_SAME_OR_EMPTY; + +public class ConceptPropertiesController { + private static final Logger LOG = LoggerFactory.getLogger(ConceptPropertiesController.class); + + public static final String CONCEPT_PROPERTIES_FXML_FILE = "concept-properties.fxml"; + + // --- add / edit tab --- + + + // --- history tab --- + + // --- hierarchy tab --- + protected static final String HIERARCHY_VIEW_FXML_FILE = "hierarchy-view.fxml"; + // --- description tab --- + + + // --- Properties Tab / Header --- + @FXML private FlowPane propertiesTabsPane; + @FXML private ToggleGroup headerTabToggleButtonGroup; // TODO: rename in FXML + @FXML private ToggleButton editButton; + @FXML private ToggleButton historyButton; + @FXML private ToggleButton hierarchyButton; + @FXML private ToggleButton commentsButton; + + // --- main view --- + @FXML private BorderPane contentBorderPane; + + // All needed state is hold in subsequent ViewModels - DO NOT hold state in this controller + @InjectViewModel + ConceptViewModelNext conceptViewModelNext; + + + // TODO : why did you do that guys :( + private StampAddSubmitFormViewModel stampAddSubmitFormViewModel; + private StampCreateFormViewModel stampCreateFormViewModel; + + private DescrNameViewModelNext descrNameViewModelNext; + + // + + // child JFXNode's created via MVVMLoader in this controller + + // 0 Stamp + private JFXNode stampFormJFXNode; + + // 1 Add/Edit + + private JFXNode menuJFXNode; + + private JFXNode nameMenuJFXNode; + + // fqn / otherName add/edit + private JFXNode nameFormJFXNode; + + + // 2 History + private Pane historyTabsBorderPane; + private HistoryChangeController historyChangeController; + + // 3 Hierarchy + private Pane hierarchyTabBorderPane; + private HierarchyController hierarchyController; + + // 4 Comments + private Pane commentsPane = new StackPane(genText("Comments Pane")); // TODO: nice missing stuff ... + + // + + + public ConceptPropertiesController() { + // we get the Concent_Topic state via ConceptViewModel + + // apperently the StampAddFormViewModel and the StampCreateFormViewModel + } + + @FXML + public void initialize() { + + createAllNodes(); + + setupStampFormBindings(); + + // ------------------------------------------------------------------------------------------------- + + // bind tab header + + // bind stampForm + + // bind nameForm + + // bind history + + // bind hirarchy + + // general propertiesController logic + + + // -- MainPain -- + SimpleObjectProperty windowToDisplay = conceptViewModelNext.getProperty(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND); + + // mainPaine <-- ViewModel + + // TODO: open respective windows - this sets up the correct values for the property ViewModels + windowToDisplay.subscribe((windowKind) -> { + if (windowKind != null) { + switch (windowKind) { + case STAMP -> { + + EntityFacade thisConceptFacade = conceptViewModelNext.getValue((ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE)); + UUID conceptTopic = conceptViewModelNext.getValue(ConceptPropertyKeys.THIS_UNIQUE_CONCEPT_TOPIC); + ViewProperties viewProperties = conceptViewModelNext.getViewProperties(); + + boolean isValidStamp = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.HAS_VALID_STAMP); + boolean isNewConcept = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + + if (isNewConcept) { + if (!isValidStamp) { + stampFormJFXNode.controller().init(stampCreateFormViewModel); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.CURRENT_STAMP_FORM, stampCreateFormViewModel); + + } // As long as newConcept we don't need to reiniate the stamp form + } else { + stampFormJFXNode.controller().init(stampAddSubmitFormViewModel); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.CURRENT_STAMP_FORM, stampAddSubmitFormViewModel); + } + + // NOTICE: call update after setting the controller above so we init the "right" ViewModel + stampFormJFXNode.controller().getStampFormViewModel().update(thisConceptFacade, conceptTopic,viewProperties); + + contentBorderPane.setCenter(stampFormJFXNode.node()); + + untoggleAllTabButtons(); + + } + case MENU -> { + LOG.info("MENU: "); + editButton.setSelected(true); + contentBorderPane.setCenter(menuJFXNode.node()); + } + case NAME_MENU -> { + LOG.info("NAME_MENU: "); + editButton.setSelected(true); + contentBorderPane.setCenter(nameMenuJFXNode.node()); + + // updateDescViewModel save() / restore() cycle + } + case NAME_FORM -> { + + LOG.info("NAME_FORM: "); + SimpleBooleanProperty hasStamp = conceptViewModelNext.getProperty(ConceptPropertyKeys.HAS_VALID_STAMP); + + // either we edit a already existing semantic -> work on semantic PublicID + // we creating a new semantic -> work on a DescName basis ? + // NO! we always work on nid f that + + // in other words we always update the DescNameViewModelNext to either have a) a sémantic PublicID b) a parent Concept Nid + // this is a invariants we can assert + + EntityFacade conceptEntity = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE); + boolean isNewConcept = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT); + + SelectedDescriptionSemantic semanticNameDescr = conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC); + boolean createNewSemantic = semanticNameDescr == null; + + if (createNewSemantic) { + LOG.info("create new semantic: "); + this.descrNameViewModelNext.createNewSemantic(conceptViewModelNext.getViewProperties()); + } else { + if (semanticNameDescr instanceof SemanticPublicId(PublicId id)) { + LOG.info("update semantic with public id: "); + this.descrNameViewModelNext.updateExistingSemantic(id, conceptViewModelNext.getViewProperties()); + } else if (semanticNameDescr instanceof UncommittedSemanticNameDescr( + DescrName value + )) { + LOG.info("update semantic with descrname: "); + this.descrNameViewModelNext.updateNonCommitedSemantic(value, conceptViewModelNext.getViewProperties()); + } + } + editButton.setSelected(true); + contentBorderPane.setCenter(nameFormJFXNode.node()); + + } + + case HISTORY -> { + historyButton.setSelected(true); + contentBorderPane.setCenter(historyTabsBorderPane); + } + case HIERARCHY -> { + hierarchyButton.setSelected(true); + contentBorderPane.setCenter(hierarchyTabBorderPane); + } + case COMMENTS -> { + commentsButton.setSelected(true); + contentBorderPane.setCenter(commentsPane); + } + case NONE -> { + untoggleAllTabButtons(); + contentBorderPane.setCenter(null); + } + } + } else { + untoggleAllTabButtons(); + contentBorderPane.setCenter(null); + // TODO: do nothing right? + } + }); + + // TODO: do we need contentCenterPane -> windowToDisplay direction ? + + // -- HeaderTab -- + // TODO: should already be wired up in the FXML + //headerTabToggleButtonGroup.getToggles().addAll(editButton, historyButton, hierarchyButton); // TODO: comments + // headerTab --> ViewModel + headerTabToggleButtonGroup.selectedToggleProperty().subscribe((newToggle) -> { + + if (editButton.equals(newToggle)) conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND,SelectedPropertyWindowKind.MENU); + else if (hierarchyButton.equals(newToggle)) conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND,SelectedPropertyWindowKind.HIERARCHY); + else if (historyButton.equals(newToggle)) conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND,SelectedPropertyWindowKind.HISTORY); + else if (commentsButton.equals(newToggle)) conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND,SelectedPropertyWindowKind.COMMENTS); + }); + + + // TODO: we can/have to remove the onAction handlers in properties-fxml as we have the toggle group now + + // + + + + } + + private void untoggleAllTabButtons() { + editButton.setSelected(false); + hierarchyButton.setSelected(false); + historyButton.setSelected(false); + commentsButton.setSelected(false); + } + + private void createAllNodes() { + // + + // 0 Stamp + + // does not hold state at this point, e.g it will only get state when something that implements StampFormViewModelBase is + // provided in the StampController on init() call + Config stampConfig = new Config(StampFormController.class.getResource(StampFormController.STAMP_FORM_FXML_FILE)); + stampFormJFXNode = FXMLMvvmLoader.make(stampConfig); + + // one of this viewModels will be put into the Node's controller above depending on the creation state of the conceptViewModel + this.stampAddSubmitFormViewModel = new StampAddSubmitFormViewModel(StampFormViewModelBase.Type.CONCEPT); + this.stampCreateFormViewModel = new StampCreateFormViewModel(StampFormViewModelBase.Type.CONCEPT); + + // 1 Add / Edit Tab + + // --- menu // TODO: no its not one is description + axiom | edit fqn + add otherName + Config menuConfig = new Config(ConceptPropertiesMenuController.class.getResource(ConceptPropertiesMenuController.EDIT_MENU_FXML_FILE)) + .addNamedViewModel(new NamedVm("conceptViewModelNext", conceptViewModelNext)); + this.menuJFXNode = FXMLMvvmLoader.make(menuConfig); + + // --- name menu + Config editDescriptionConfig = new Config(ConceptPropertiesNameMenuController.class.getResource(ConceptPropertiesNameMenuController.EDIT_MENU_FXML_FILE)) + .addNamedViewModel(new NamedVm("conceptViewModelNext", conceptViewModelNext)); + this.nameMenuJFXNode = FXMLMvvmLoader.make(editDescriptionConfig); + + + // --- nameForm to Add/Edit FQN or otherName + // TODO: maybe the same update trick to the viewModel / Controller as in stamp to the descViewModelNext -> it needs + DescrNameViewModelNext descrNameViewModelNext = new DescrNameViewModelNext(conceptViewModelNext.getViewProperties()); + + Config nameConfig = new Config(ConceptPropertiesNameFormController.class.getResource(ConceptPropertiesNameFormController.CONCEPT_PROP_NAMES_FXML_FILE)); + nameConfig.addNamedViewModel(new NamedVm("descrNameViewModelNext", descrNameViewModelNext)); + nameConfig.addNamedViewModel(new NamedVm("conceptViewModelNext", conceptViewModelNext)); +// Config nameConfig = new Config( +// ConceptPropertiesNameFormController.class.getResource(ConceptPropertiesNameFormController.CONCEPT_PROP_NAMES_FXML_FILE), +// new NamedVm("descrNameViewModelNext", descrNameViewModelNext)) +// .addNamedViewModel(new NamedVm("conceptViewModelNext", conceptViewModelNext)); + this.nameFormJFXNode = FXMLMvvmLoader.make(nameConfig); + + + this.descrNameViewModelNext = descrNameViewModelNext; + + + // 2 History Tab TODO: update to MVVM + FXMLLoader loader = new FXMLLoader( HistoryChangeController.class.getResource(HistoryChangeController.HISTORY_CHANGE_FXML_FILE)); + try { historyTabsBorderPane = loader.load();} catch (IOException e) { + throw new RuntimeException(e); + } + + historyChangeController = loader.getController(); + + // 3 Hierarchy TabTODO: update to MVVM + FXMLLoader loader2 = new FXMLLoader(HierarchyController.class.getResource(HIERARCHY_VIEW_FXML_FILE)); + try { hierarchyTabBorderPane = loader2.load(); } catch (IOException e) { + throw new RuntimeException(e); + } + hierarchyController = loader2.getController(); + + // 4 Comments Tab TODO: implement :( + + // + } + + private void setupStampFormBindings() { + SimpleBooleanProperty confirmedPressedProperty = this.stampCreateFormViewModel.getProperty(IS_CONFIRMED_OR_SUBMITTED); + confirmedPressedProperty.subscribe( (wasPressed, isPressed) -> { + if (isPressed) { + LOG.info("Confirmed pressed on stampCreate Form"); + boolean isStampSame = stampCreateFormViewModel.getPropertyValue(IS_STAMP_VALUES_THE_SAME_OR_EMPTY); + if (!isStampSame) { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.HAS_VALID_STAMP, true); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NONE); + confirmedPressedProperty.setValue(false); + } + } + }); + + SimpleBooleanProperty submittedPressedProperty = this.stampAddSubmitFormViewModel.getProperty(IS_CONFIRMED_OR_SUBMITTED); + submittedPressedProperty.subscribe(isSubmitted -> { + if (isSubmitted) { + LOG.info("STAMP submit form: sbmit button pressed"); + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.HAS_VALID_STAMP, true); // TODO is this correct? + } + }); + + } + + public HistoryChangeController getHistoryChangeController() { + return historyChangeController; + } + + public HierarchyController getHierarchyController() { + return hierarchyController; + } + + + public StampFormViewModelBase getStampFormViewModel() { + return conceptViewModelNext.getPropertyValue(ConceptPropertyKeys.CURRENT_STAMP_FORM); + } + + /** + * Returns the propertiesTabsPane to be used as a draggable region. + * @return The FlowPane containing the property tabs + */ + public FlowPane getPropertiesTabsPane() { + return propertiesTabsPane; + } +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesMenuController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesMenuController.java new file mode 100644 index 0000000000..a9860e6def --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesMenuController.java @@ -0,0 +1,50 @@ +package dev.ikm.komet.kview.mvvm.view.concept; + + + +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext;import javafx.beans.binding.Bindings; +import javafx.beans.property.SimpleStringProperty; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ConceptPropertiesMenuController { + private static final Logger LOG = LoggerFactory.getLogger(ConceptPropertiesMenuController.class); + + public static final String EDIT_MENU_FXML_FILE = "concept-prop-menu.fxml"; + + @FXML private Label conceptTitleLabel; + @FXML private Button editDescriptionsButton; + @FXML private Button editAxiomsButton; + + @InjectViewModel + ConceptViewModelNext conceptViewModelNext; + + public ConceptPropertiesMenuController() { + + } + + @FXML + public void initialize() { + + // TODO: + SimpleStringProperty fqnTitleTextProp = conceptViewModelNext.getProperty("add fqn text to conceptModel. E.g get it via NID"); + + conceptTitleLabel.textProperty().bind( + Bindings.concat("Edit: ", fqnTitleTextProp) + ); + + // open the name menu pane + editDescriptionsButton.setOnMouseClicked(mouseEvent -> { + conceptViewModelNext.setPropertyValue(ConceptViewModelNext.ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, ConceptViewModelNext.SelectedPropertyWindowKind.NAME_MENU); + + }); + + // TODO: editAxiomsButton when Axiom Controller is implemented + } + +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameFormController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameFormController.java new file mode 100644 index 0000000000..232551833c --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameFormController.java @@ -0,0 +1,240 @@ +package dev.ikm.komet.kview.mvvm.view.concept; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.common.ViewCalculatorUtils; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext.*; +import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModelNext; +import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModelNext.*; +import dev.ikm.tinkar.terms.ComponentWithNid; +import javafx.beans.binding.BooleanBinding; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.VBox; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConceptPropertiesNameFormController { + private static final Logger LOG = LoggerFactory.getLogger(ConceptPropertiesNameFormController.class); + + public static final String CONCEPT_PROP_NAMES_FXML_FILE = "concept-prop-name-form.fxml"; + + // + @FXML private Label titleLabel; + + //
+ @FXML private TextField nameTextField; // holds either FQN or otherName + @FXML private ComboBox typeDisplayComboBox; // TODO: check recent commits if still disabled in FXML + @FXML private ComboBox caseSignificanceComboBox; + @FXML private ComboBox statusComboBox; + @FXML private ComboBox moduleComboBox; + @FXML private ComboBox languageComboBox; + + // Dialects (visible once a language is selected) //TODO: make that happen + @FXML private VBox dialectsContainer; + @FXML private Label dialect1Label; + @FXML private Label dialect2Label; + @FXML private Label dialect3Label; + @FXML private ComboBox dialectComboBox1; + @FXML private ComboBox dialectComboBox2; + @FXML private ComboBox dialectComboBox3; + + @FXML private Label commentsLabel; // // TODO remove as unused + + @FXML private TextArea commentsTextArea; + + + // + @FXML private Button submitButton; + @FXML private Button cancelButton; + + + @InjectViewModel + private ConceptViewModelNext conceptViewModelNext; + + @InjectViewModel + private DescrNameViewModelNext descrNameViewModelNext; + + public ConceptPropertiesNameFormController() { + // conceptTopic is available through ConceptViewModel + } + + @FXML + public void initialize() { + + + initFormTitle(); + + initNameText(); + + initTypeComboBox(); + initCaseSignificanceComboBox(); + initStatusComboBox(); + initModuleComboBox(); + initLanguageComboBox(); + + bindLanguageSelectionToDialects(); + + // -- bottom buttons -- + submitButton.disableProperty().bind(descrNameViewModelNext.invalidProperty()); // TODO, use validator that already present + cancelButton.setOnMouseClicked(mouseEvent -> { // TODO: conceptViewModel update + closeView(); + }); + } + + private ViewProperties getViewProperties() { + return conceptViewModelNext.getViewProperties(); + } + + private void initFormTitle() { + titleLabel.textProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.TITLE_TEXT)); + } + + private void initNameText() { + titleLabel.textProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.NAME)); + } + + private void initTypeComboBox() { + ViewCalculatorUtils.initComboBox( + typeDisplayComboBox, + descrNameViewModelNext.getObservableList(DescrPropKeys.NAME_TYPE_VARIANTS), + this::getViewProperties); + + + typeDisplayComboBox.valueProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.SELECTED_NAME_TYPE)); + } + + private void initCaseSignificanceComboBox() { + ViewCalculatorUtils.initComboBox( + caseSignificanceComboBox, + descrNameViewModelNext.getObservableList(DescrPropKeys.CASE_SIGNIFICANCE_VARIANTS), + this::getViewProperties); + + caseSignificanceComboBox.valueProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.SELECTED_CASE_SIGNIFICANCE)); + } + + private void initStatusComboBox() { + ViewCalculatorUtils.initComboBox( + statusComboBox, + descrNameViewModelNext.getObservableList(DescrPropKeys.STATUS_VARIANTS), + this::getViewProperties); + + statusComboBox.valueProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.SELECTED_STATUS)); + } + + private void initModuleComboBox() { + ViewCalculatorUtils.initComboBox( + moduleComboBox, + descrNameViewModelNext.getObservableList(DescrPropKeys.MODULE_VARIANTS), + this::getViewProperties); + + moduleComboBox.valueProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.SELECTED_MODULE)); + } + + private void initLanguageComboBox() { + ViewCalculatorUtils.initComboBox( + languageComboBox, + descrNameViewModelNext.getObservableList(DescrPropKeys.LANGUAGE_VARIANTS), + this::getViewProperties); + + languageComboBox.valueProperty().bindBidirectional(descrNameViewModelNext.getProperty(DescrPropKeys.SELECTED_LANGUAGE)); + } + + private void bindLanguageSelectionToDialects() { + // TODO: enable it after cleaning up the layout +// BooleanBinding isLanguageSelected = languageComboBox.valueProperty().isNotNull(); +// dialectsContainer.visibleProperty().bind(isLanguageSelected); + } + + + @FXML + private void onCancel(ActionEvent actionEvent) { + actionEvent.consume(); + + closeView(); + } + + @FXML + private void onSubmit(ActionEvent actionEvent) { + actionEvent.consume(); + + // implicitly calls validate +// descrNameViewModelNext.save(); +// +// // check the validation result +// if (descrNameViewModelNext.hasErrorMsgs()) { +// descrNameViewModelNext.getValidationMessages().forEach(msg -> LOG.error("Validation error {}", msg)); +// return; +// } +// +// // validate check ok -> save copied the ViewProperties into ModelProperties +// // we build a record out of the updated ModelProerties +// DescrName record = descrNameViewModelNext.create(); // TODO: check why SMEANTIC_PUB_ID and PARENT_PUB_ID are needed | do they need exist befor this? +// +// // check if we are in create or view/edit mode +// String mode = conceptViewModel.getValue(MODE); +// +// +// PublicId thisNamePublicId = conceptViewModel.getValue(SELECTED_NAME_DESCRIPTION_PUBLIC_ID); +// ConceptViewModel.SelectedNameDescriptionKind thisNameKind = conceptViewModel.getValue(SELECTED_NAME_DESCRIPTION_KIND); +// +// +// +// if (CREATE.equals(mode)) { // than we have no publicID for this name -> but the record itself should track that info +// switch (thisNameKind) { +// case FQN -> { +// ObservableList fqnNames = conceptViewModel.getObservableList(ADDED_BUT_NOT_COMMITED_FQN_NAME_RECORDS); +// fqnNames.add(record); +// } +// case otherName -> { +// ObservableList otherNames = conceptViewModel.getObservableList(ADDED_BUT_NOT_COMMITED_OTHER_NAME_RECORDS); +// otherNames.add(record); // TODO does this trigger an update of the model or do we need to reinsert? +// } +// } +// +// } else { // edit/view mode TODO: is it allowed to add name / kind in edit view mode? +// +// ViewProperties viewProperties = conceptViewModel.getViewProperties(); +// +// if (thisNamePublicId != null) { // this is a Name we Edit +// switch (thisNameKind) { +// case FQN -> { // TODO: investigate if this calls should be decoupled like in Pattern ? +// // THIS CALL DOES NOT UPDATE THE VIEWMODEL BUT THE DB (cache?) +// descrNameViewModelNext.updateFullyQualifiedName(thisNamePublicId,viewProperties); +// } +// case otherName -> { +// // THIS CALL DOES NOT UPDATE THE VIEWMODEL BUT THE DB (cache?) +// descrNameViewModelNext.updateOtherName(thisNamePublicId,viewProperties); +// } +// } +// } else { // this is a Name we Add to existing ones +// +// switch (thisNameKind) { +// case FQN -> { +// ObservableList fqnNames = conceptViewModel.getObservableList(ADDED_BUT_NOT_COMMITED_FQN_NAME_RECORDS); +// fqnNames.add(record); +// } +// case otherName -> { +// ObservableList otherNames = conceptViewModel.getObservableList(ADDED_BUT_NOT_COMMITED_OTHER_NAME_RECORDS); +// otherNames.add(record); // TODO does this trigger an update of the model or do we need to reinsert? +// } +// } +// } +// +// } + + // TODO: should we clear the associate descrViewModel? i think its better to always start with a fresh one for a window. + + closeView(); + + + } + + private void closeView() { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NONE); + } + +} + diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameMenuController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameMenuController.java new file mode 100644 index 0000000000..a350d9bd4f --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/concept/ConceptPropertiesNameMenuController.java @@ -0,0 +1,64 @@ +package dev.ikm.komet.kview.mvvm.view.concept; + + + +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext; +import dev.ikm.komet.kview.mvvm.viewmodel.ConceptViewModelNext.*; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import org.carlfx.cognitive.loader.InjectViewModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConceptPropertiesNameMenuController { + private static final Logger LOG = LoggerFactory.getLogger(ConceptPropertiesNameMenuController.class); + + public static final String EDIT_MENU_FXML_FILE = "concept-prop-name-menu.fxml"; + + @FXML private Button editFullyQualifiedNameButton; + @FXML private Button closePropertiesPanelButton; + @FXML private Button addOtherNameButton; + + @InjectViewModel + ConceptViewModelNext conceptViewModelNext; + + public ConceptPropertiesNameMenuController() { + + } + + @FXML + public void initialize() { + + ObservableList fqnSemanticProps = conceptViewModelNext.getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS); + fqnSemanticProps.subscribe(() -> { + if(fqnSemanticProps.isEmpty()) { + editFullyQualifiedNameButton.setText("ADD FULLY QUALIFIED"); + } else { + editFullyQualifiedNameButton.setText("EDIT FULLY QUALIFIED"); + } + }); + + if(fqnSemanticProps.isEmpty()) { + editFullyQualifiedNameButton.setText("ADD FULLY QUALIFIED"); + } else { + editFullyQualifiedNameButton.setText("EDIT FULLY QUALIFIED"); + } + + + editFullyQualifiedNameButton.setOnMouseClicked( mouseEvent -> { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + + }); + + addOtherNameButton.setOnMouseClicked( mouseEvent -> { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NAME_FORM); + + }); + + closePropertiesPanelButton.setOnMouseClicked(mouseEvent -> { + conceptViewModelNext.setPropertyValue(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, SelectedPropertyWindowKind.NONE); + }); + + } +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/journal/JournalController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/journal/JournalController.java index 65910d41ad..0f70560dae 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/journal/JournalController.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/journal/JournalController.java @@ -1230,8 +1230,7 @@ private void setupWorkspaceWindow(ChapterKlWindow chapterKlWindow) { } // Getting the details node from the concept window - ConceptNode conceptNode = conceptKlWindow.getDetailsNode(); - conceptNode.getConceptDetailsViewController().onReasonerSlideoutTray(reasonerToggleConsumer); + conceptKlWindow.getConceptController().onReasonerSlideoutTray(reasonerToggleConsumer); } } diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddFullyQualifiedNameController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddFullyQualifiedNameController.java deleted file mode 100644 index 637c8ce25e..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddFullyQualifiedNameController.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.IS_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TYPE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_TYPE; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; -import dev.ikm.komet.kview.events.CreateConceptEvent; -import dev.ikm.komet.kview.mvvm.model.DescrName; -import dev.ikm.komet.kview.mvvm.view.AbstractBasicController; -import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; -import dev.ikm.tinkar.common.id.PublicId; -import dev.ikm.tinkar.entity.ConceptEntity; -import dev.ikm.tinkar.entity.Entity; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.State; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.beans.InvalidationListener; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.TextField; -import javafx.util.Callback; -import javafx.util.StringConverter; -import org.carlfx.cognitive.loader.InjectViewModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Optional; -import java.util.UUID; - -public class AddFullyQualifiedNameController extends AbstractBasicController { - - private static final Logger LOG = LoggerFactory.getLogger(AddFullyQualifiedNameController.class); - - private UUID conceptTopic; - - @FXML - private Label addFqnTitleLabel; - - @FXML - private TextField fullyQualifiedNameTextField; - - @FXML - private ComboBox typeDisplayComboBox; - - @FXML - private ComboBox caseSignificanceComboBox; - - @FXML - private ComboBox statusComboBox; - - @FXML - private ComboBox moduleComboBox; - - @FXML - private ComboBox languageComboBox; - - @FXML - private Button submitButton; - - private EvtBus eventBus; - - private ViewProperties viewProperties; - - private PublicId publicId; - - @InjectViewModel - private DescrNameViewModel fqnViewModel; - - public AddFullyQualifiedNameController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - @FXML - public void initialize() { - eventBus = EvtBusFactory.getDefaultEvtBus(); - clearView(); - submitButton.setDisable(true); - - - // Initialize the fqnViewModel - fqnViewModel - .setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE) - .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); - - // register listeners - InvalidationListener formValid = (obs) -> { - boolean isFormValid = isFormPopulated(); - if (isFormValid) { - copyUIToViewModelProperties(); - } - submitButton.setDisable(!isFormValid); - }; - - fullyQualifiedNameTextField.textProperty().addListener(formValid); - setupComboBox(moduleComboBox, formValid); - setupComboBox(statusComboBox, formValid); - setupComboBox(caseSignificanceComboBox, formValid); - setupComboBox(languageComboBox, formValid); - setupComboBox(typeDisplayComboBox, formValid); - } - - /** - * TODO: This is appropriate. A better solution is binding properties on the view model. If so, we'd need to unbind. - * This copies form values into the ViewModel's property values. It does not save or validate. - */ - private void copyUIToViewModelProperties() { - if (fqnViewModel != null) { - fqnViewModel.setPropertyValue(NAME_TEXT, fullyQualifiedNameTextField.getText()) - .setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE) - .setPropertyValue(CASE_SIGNIFICANCE, caseSignificanceComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(STATUS, statusComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(MODULE, moduleComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(LANGUAGE, languageComboBox.getSelectionModel().getSelectedItem()); - } - } - - public void populate(ComboBox comboBox, Collection entities) { - comboBox.getItems().setAll(entities); - } - - @Override - public void updateView() { - - // populate form combo fields module, status, case significance, lang. - populate(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); - populate(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.STATUS_VALUE.publicId())); - populate(caseSignificanceComboBox, fqnViewModel.findAllCaseSignificants(getViewProperties())); - populate(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); - populate(typeDisplayComboBox, fetchDescendentsOfConcept(getViewProperties(), DESCRIPTION_TYPE.publicId())); - - // Set UI to default values - caseSignificanceComboBox.setValue(TinkarTerm.DESCRIPTION_NOT_CASE_SENSITIVE); - statusComboBox.setValue(Entity.getFast(State.ACTIVE.nid())); - moduleComboBox.setValue(TinkarTerm.DEVELOPMENT_MODULE); - languageComboBox.setValue(TinkarTerm.ENGLISH_LANGUAGE); - typeDisplayComboBox.setValue(TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE); - - } - - @Override - public void clearView() { - fullyQualifiedNameTextField.setText(""); - moduleComboBox.setValue(null); - statusComboBox.setValue(null); - caseSignificanceComboBox.setValue(null); - languageComboBox.setValue(null); - moduleComboBox.getItems().clear(); - statusComboBox.getItems().clear(); - caseSignificanceComboBox.getItems().clear(); - languageComboBox.getItems().clear(); - } - - @Override - public void cleanup() { - - } - - private boolean isFormPopulated() { - return (fullyQualifiedNameTextField.getText() != null && !fullyQualifiedNameTextField.getText().toString().isEmpty()) - && (moduleComboBox.getSelectionModel().getSelectedItem() != null) - && (statusComboBox.getSelectionModel().getSelectedItem() != null) - && (caseSignificanceComboBox.getSelectionModel().getSelectedItem() != null) - && (languageComboBox.getSelectionModel().getSelectedItem() != null); - } - - private String getDisplayText(ConceptEntity conceptEntity) { - Optional stringOptional = getViewProperties().calculator().getRegularDescriptionText(conceptEntity.nid()); - return stringOptional.orElse(""); - } - - private void setupComboBox(ComboBox comboBox, InvalidationListener listener) { - comboBox.setConverter(new StringConverter() { - - @Override - public String toString(ConceptEntity conceptEntity) { - return getDisplayText(conceptEntity); - } - - @Override - public ConceptEntity fromString(String string) { - return null; - } - }); - - comboBox.setCellFactory(new Callback<>() { - - /** - * @param param The single argument upon which the returned value should be - * determined. - * @return - */ - @Override - public ListCell call(Object param) { - return new ListCell<>(){ - @Override - protected void updateItem(ConceptEntity conceptEntity, boolean b) { - super.updateItem(conceptEntity, b); - if (conceptEntity != null) { - setText(getDisplayText(conceptEntity)); - } else { - setText(null); - } - - } - }; - } - }); - - // register invalidation listener - comboBox.getSelectionModel().selectedItemProperty().addListener(listener); - } - - @FXML - private void saveFullQualifiedName(ActionEvent actionEvent) { - actionEvent.consume(); - - // TODO assuming it's valid save() check for errors and publish event - - fqnViewModel.save(); - if (fqnViewModel.getValidationMessages().size() == 0) { - // publish event with the fqnViewModel. - // ... This property may not be needed. - fqnViewModel.setPropertyValue(IS_SUBMITTED, true); - } - - LOG.info("Ready to add to the concept view model: " + fqnViewModel); - - ////////////////////////////////////////////////////////////////////////////////////////// - // event received in Details Controller that will call conceptViewModel.createConcept() - ////////////////////////////////////////////////////////////////////////////////////////// - DescrName fqnDescrName = fqnViewModel.create(); - eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_FQN, fqnDescrName)); - - // clear the form after saving. otherwise when you navigate back to Add Other Name - // you would have the previous form values still there - clearView(); - close(); - } - - @FXML - public void handleCancelButtonEvent() { - close(); - } - - private void close() { - // close the properties bump out - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - @Override - public DescrNameViewModel getViewModel() { - return fqnViewModel; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddOtherNameController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddOtherNameController.java deleted file mode 100644 index b2824704de..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/AddOtherNameController.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.IS_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TYPE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.DESCRIPTION_CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.DESCRIPTION_LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.HAS_OTHER_NAME; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_TYPE; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; -import dev.ikm.komet.kview.events.CreateConceptEvent; -import dev.ikm.komet.kview.mvvm.view.AbstractBasicController; -import dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel; -import dev.ikm.tinkar.entity.ConceptEntity; -import dev.ikm.tinkar.entity.Entity; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.State; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.beans.InvalidationListener; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.TextField; -import javafx.util.Callback; -import javafx.util.StringConverter; -import org.carlfx.cognitive.loader.InjectViewModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Optional; -import java.util.UUID; - -public class AddOtherNameController extends AbstractBasicController { - - private static final Logger LOG = LoggerFactory.getLogger(AddOtherNameController.class); - - private UUID conceptTopic; - - @FXML - private Label addOtherNameTitleLabel; - - @FXML - private TextField otherNameTextField; - - @FXML - private ComboBox typeDisplayComboBox; - - @FXML - private ComboBox caseSignificanceComboBox; - - @FXML - private ComboBox statusComboBox; - - @FXML - private ComboBox moduleComboBox; - - @FXML - private ComboBox languageComboBox; - - @FXML - private Button submitButton; - - private EvtBus eventBus; - - private ViewProperties viewProperties; - - private EntityFacade entityFacade; - - @InjectViewModel - private OtherNameViewModel otherNameViewModel; - - - public AddOtherNameController() { } - - public AddOtherNameController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - @FXML - public void initialize() { - eventBus = EvtBusFactory.getDefaultEvtBus(); - clearView(); - submitButton.setDisable(true); - setAddOtherNameTitleLabel("Add New Description: Other Name"); - // Initialize view models - otherNameViewModel - .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) - .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); - // register listeners - InvalidationListener formValid = (obs) -> { - boolean isFormValid = isFormPopulated(); - if (isFormValid) { - copyUIToViewModelProperties(); - } - submitButton.setDisable(!isFormValid); - }; - - otherNameTextField.textProperty().addListener(formValid); - setupComboBox(moduleComboBox, formValid); - setupComboBox(statusComboBox, formValid); - setupComboBox(caseSignificanceComboBox, formValid); - setupComboBox(languageComboBox, formValid); - setupComboBox(typeDisplayComboBox, formValid); - } - - /** - * TODO: This is appropriate. A better solution is binding properties on the view model. If so, we'd need to unbind. - * This copies form values into the ViewModel's property values. It does not save or validate. - */ - private void copyUIToViewModelProperties() { - if (otherNameViewModel != null) { - otherNameViewModel.setPropertyValue(NAME_TEXT, otherNameTextField.getText()) - .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) - .setPropertyValue(CASE_SIGNIFICANCE, caseSignificanceComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(STATUS, statusComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(MODULE, moduleComboBox.getSelectionModel().getSelectedItem()) - .setPropertyValue(LANGUAGE, languageComboBox.getSelectionModel().getSelectedItem()); - } - } - - public void updateModel(final ViewProperties viewProperties) { - this.viewProperties = viewProperties; - } - - public void populate(ComboBox comboBox, Collection entities) { - comboBox.getItems().addAll(entities); - } - - - @Override - public OtherNameViewModel getViewModel() { - return otherNameViewModel; - } - - - private String getDisplayText(ConceptEntity conceptEntity) { - Optional stringOptional = getViewProperties().calculator().languageCalculator().getRegularDescriptionText(conceptEntity.nid()); - return stringOptional.orElse(""); - } - - private void setupComboBox(ComboBox comboBox, InvalidationListener listener) { - comboBox.setConverter(new StringConverter() { - - @Override - public String toString(ConceptEntity conceptEntity) { - return getDisplayText(conceptEntity); - } - - @Override - public ConceptEntity fromString(String string) { - return null; - } - }); - - comboBox.setCellFactory(new Callback<>() { - - /** - * @param param The single argument upon which the returned value should be - * determined. - * @return - */ - @Override - public ListCell call(Object param) { - return new ListCell<>(){ - @Override - protected void updateItem(ConceptEntity conceptEntity, boolean b) { - super.updateItem(conceptEntity, b); - if (conceptEntity != null) { - setText(getDisplayText(conceptEntity)); - } else { - setText(null); - } - - } - }; - } - }); - - // register invalidation listener - comboBox.getSelectionModel().selectedItemProperty().addListener(listener); - } - - private boolean isFormPopulated() { - return (otherNameTextField.getText() != null && !otherNameTextField.getText().toString().isEmpty()) - && (moduleComboBox.getSelectionModel().getSelectedItem() != null) - && (statusComboBox.getSelectionModel().getSelectedItem() != null) - && (caseSignificanceComboBox.getSelectionModel().getSelectedItem() != null) - && (languageComboBox.getSelectionModel().getSelectedItem() != null); - } - - public void setAddOtherNameTitleLabel(String addDescriptionTitleLabelText) { - this.addOtherNameTitleLabel.setText(addDescriptionTitleLabelText); - } - - @FXML - private void saveOtherName(ActionEvent actionEvent) { - actionEvent.consume(); - - // TODO assuming it's valid save() check for errors and publish event - otherNameViewModel.setPropertyValue(IS_SUBMITTED, true); - otherNameViewModel.save(); - if (otherNameViewModel.hasNoErrorMsgs()) { - // publish event with the otherNameViewModel. - // ... - LOG.info("Ready to add to the concept view model: " + otherNameViewModel); - eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_OTHER_NAME, - otherNameViewModel.create())); - clearView(); - close(); - } - - } - - - @Override - public void updateView() { - // populate form combo fields module, status, case significance, lang. - populate(typeDisplayComboBox, fetchDescendentsOfConcept(getViewProperties(), DESCRIPTION_TYPE.publicId())); - populate(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); - populate(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.STATUS_VALUE.publicId())); - populate(caseSignificanceComboBox, otherNameViewModel.findAllCaseSignificants(getViewProperties())); - populate(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); - - typeDisplayComboBox.setValue(TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE); - - boolean hasOtherName = getViewModel().getValue(HAS_OTHER_NAME); - - if (hasOtherName) { - caseSignificanceComboBox.setValue(getViewModel().getValue(DESCRIPTION_CASE_SIGNIFICANCE)); - } else { - caseSignificanceComboBox.setValue(TinkarTerm.DESCRIPTION_NOT_CASE_SENSITIVE); - } - statusComboBox.setValue(Entity.getFast(State.ACTIVE.nid())); - moduleComboBox.setValue(TinkarTerm.DEVELOPMENT_MODULE); - if (hasOtherName) { - languageComboBox.setValue(getViewModel().getValue(DESCRIPTION_LANGUAGE)); - } else { - languageComboBox.setValue(TinkarTerm.ENGLISH_LANGUAGE); - } - } - - - @Override - public void clearView() { - otherNameTextField.setText(""); - moduleComboBox.setValue(null); - statusComboBox.setValue(null); - caseSignificanceComboBox.setValue(null); - languageComboBox.setValue(null); - moduleComboBox.getItems().clear(); - statusComboBox.getItems().clear(); - caseSignificanceComboBox.getItems().clear(); - languageComboBox.getItems().clear(); - } - - @FXML - public void handleCancelButtonEvent() { - close(); - } - - private void close() { - // close the properties bump out - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - @Override - public void cleanup() { - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditConceptController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditConceptController.java deleted file mode 100644 index 36a6aadc0c..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditConceptController.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import dev.ikm.komet.kview.mvvm.view.BasicController; -import dev.ikm.komet.kview.events.OpenPropertiesPanelEvent; -import dev.ikm.komet.kview.events.ShowEditDescriptionPanelEvent; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.events.Subscriber; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.UUID; - -public class EditConceptController implements BasicController { - - private static final Logger LOG = LoggerFactory.getLogger(EditConceptController.class); - - - private static final String EDIT_LABEL_PREFIX = "Edit: "; - - @FXML - private Label conceptTitleLabel; - - @FXML - private Button editDescriptionsButton; - - @FXML - private Button editAxiomsButton; - - private Subscriber propsPanelOpen; - - private EvtBus eventBus; - - private UUID conceptTopic; - - - public EditConceptController() { } - - public EditConceptController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - @FXML - @Override - public void initialize() { - clearView(); - - eventBus = EvtBusFactory.getDefaultEvtBus(); - - propsPanelOpen = evt -> { - setConceptTitleLabel(evt.getConceptFQName()); - }; - eventBus.subscribe(conceptTopic, OpenPropertiesPanelEvent.class, propsPanelOpen); - - // when the user clicks the ADD DESCRIPTION button - // on the Journal > Concept > Properties bump out > Edit tab - // publish an event so that the concept detail window can - // listen for it and swap the pane in the bump out to be the - // add description form - editDescriptionsButton.setOnMouseClicked(event -> { - eventBus.publish(conceptTopic, - new ShowEditDescriptionPanelEvent(this, - ShowEditDescriptionPanelEvent.SHOW_EDIT_DESCRIPTION)); - }); - - // the addAxiomsButton doesn't do anything at this time since it - // is part of a mock-up for future functionality - } - - private void setConceptTitleLabel(String conceptTitleLabel) { - this.conceptTitleLabel.setText(EDIT_LABEL_PREFIX + conceptTitleLabel); - } - - @Override - public void updateView() { } - - @Override - public void clearView() { } - - @Override - public void cleanup() { } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java deleted file mode 100644 index 1635d5f7f9..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionFormController.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.IS_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TYPE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_TYPE; -import static dev.ikm.tinkar.terms.TinkarTerm.LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; -import dev.ikm.komet.kview.events.CreateConceptEvent; -import dev.ikm.komet.kview.mvvm.model.DescrName; -import dev.ikm.komet.kview.mvvm.view.BasicController; -import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; -import dev.ikm.tinkar.common.id.IntIdSet; -import dev.ikm.tinkar.common.id.PublicId; -import dev.ikm.tinkar.coordinate.stamp.calculator.Latest; -import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator; -import dev.ikm.tinkar.entity.ConceptEntity; -import dev.ikm.tinkar.entity.Entity; -import dev.ikm.tinkar.entity.EntityService; -import dev.ikm.tinkar.entity.EntityVersion; -import dev.ikm.tinkar.entity.PatternEntity; -import dev.ikm.tinkar.entity.PatternEntityVersion; -import dev.ikm.tinkar.entity.SemanticEntityVersion; -import dev.ikm.tinkar.entity.StampEntity; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.terms.ConceptFacade; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.beans.InvalidationListener; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.TextField; -import javafx.util.Callback; -import javafx.util.StringConverter; -import org.carlfx.cognitive.loader.InjectViewModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -public class EditDescriptionFormController implements BasicController { - - private static final Logger LOG = LoggerFactory.getLogger(EditDescriptionFormController.class); - - private UUID conceptTopic; - - private EntityFacade entityFacade; - - private Map> descriptionSemanticsMap; - - private ViewProperties viewProperties; - - @FXML - private TextField otherNameTextField; - - @FXML - private ComboBox typeDisplayComboBox; - - @FXML - private ComboBox caseSignificanceComboBox; - - @FXML - private ComboBox statusComboBox; - - @FXML - private ComboBox moduleComboBox; - - @FXML - private ComboBox languageComboBox; - - @FXML - private Label editDescriptionTitleLabel; - - @FXML - private Label dialect1Label; - - @FXML - private Label dialect2Label; - - @FXML - private Label dialect3Label; - - @FXML - private ComboBox dialectComboBox1; - - @FXML - private ComboBox dialectComboBox2; - - @FXML - private ComboBox dialectComboBox3; - - @FXML - private Button submitButton; - - @FXML - private Button cancelButton; - - private PublicId publicId; - - private EvtBus eventBus; - - @InjectViewModel - private DescrNameViewModel otherNameViewModel; - - public EditDescriptionFormController() { } - - public EditDescriptionFormController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - @Override - @FXML - public void initialize() { - eventBus = EvtBusFactory.getDefaultEvtBus(); - clearView(); - setEditDescriptionTitleLabel("Edit Description: Other Name"); - - otherNameViewModel - .setPropertyValue(NAME_TYPE, TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE) - .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE); - - populateDialectComboBoxes(); - - // bind with viewmodel. - otherNameTextField.textProperty().bindBidirectional(otherNameViewModel.getProperty(NAME_TEXT)); - moduleComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(MODULE)); - caseSignificanceComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(CASE_SIGNIFICANCE)); - statusComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(STATUS)); - languageComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(LANGUAGE)); - typeDisplayComboBox.valueProperty().bindBidirectional(otherNameViewModel.getProperty(NAME_TYPE)); - - InvalidationListener invalidationListener = obs -> validateForm(); - - otherNameTextField.textProperty().addListener(invalidationListener); - moduleComboBox.valueProperty().addListener(invalidationListener); - caseSignificanceComboBox.valueProperty().addListener(invalidationListener); - statusComboBox.valueProperty().addListener(invalidationListener); - languageComboBox.valueProperty().addListener(invalidationListener); - typeDisplayComboBox.valueProperty().addListener(invalidationListener); - validateForm(); - } - - @FXML - private void handleCancelButtonEvent() { - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(cancelButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - private boolean isFormPopulated() { - return (otherNameTextField.getText() != null && !otherNameTextField.getText().toString().isEmpty()) - && (moduleComboBox.getSelectionModel().getSelectedItem() != null) - && (statusComboBox.getSelectionModel().getSelectedItem() != null) - && (caseSignificanceComboBox.getSelectionModel().getSelectedItem() != null) - && (languageComboBox.getSelectionModel().getSelectedItem() != null); - } - - private void validateForm() { - boolean isOtherNameTextFieldEmpty = otherNameTextField.getText().trim().isEmpty(); - boolean isModuleComboBoxSelected = moduleComboBox.getValue() != null; - boolean isCaseSignificanceComboBoxSelected = caseSignificanceComboBox.getValue() != null; - boolean isStatusComboBoxComboBoxSelected = statusComboBox.getValue() != null; - boolean isLanguageComboBoxComboBoxSelected = languageComboBox.getValue() != null; - - submitButton.setDisable( - isOtherNameTextFieldEmpty || !isModuleComboBoxSelected - || !isCaseSignificanceComboBoxSelected || !isLanguageComboBoxComboBoxSelected - || !isStatusComboBoxComboBoxSelected); - } - - private void populateDialectComboBoxes() { - // currently no UNACCEPTABLE in TinkarTerm - Entity acceptable = EntityService.get().getEntityFast(TinkarTerm.ACCEPTABLE); - Entity preferred = EntityService.get().getEntityFast(TinkarTerm.PREFERRED); - - // each combo box has a separate list instance - setupComboBox(dialectComboBox1, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox1.getSelectionModel().select(Entity.getFast(acceptable.nid())); - setupComboBox(dialectComboBox2, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox2.getSelectionModel().select(Entity.getFast(preferred.nid())); - setupComboBox(dialectComboBox3, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox3.getSelectionModel().select(Entity.getFast(preferred.nid())); - } - - public void setEditDescriptionTitleLabel(String addAxiomTitleLabelText) { - this.editDescriptionTitleLabel.setText(addAxiomTitleLabelText); - } - - @Override - public void updateView() { - - } - - @Override - public void clearView() { - caseSignificanceComboBox.getItems().clear(); - statusComboBox.getItems().clear(); - moduleComboBox.getItems().clear(); - languageComboBox.getItems().clear(); - } - - @Override - public void cleanup() { - - } - - public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade) { - this.viewProperties = viewProperties; - this.entityFacade = entityFacade; - } - - private ViewProperties getViewProperties() { - return this.viewProperties; - } - - private String getDisplayText(ConceptEntity conceptEntity) { - if (conceptEntity != null) { - Optional stringOptional = getViewProperties().calculator().getRegularDescriptionText(conceptEntity.nid()); - return stringOptional.orElse(""); - } else { - return ""; - } - } - - private void setupComboBox(ComboBox comboBox, Collection conceptEntities) { - comboBox.getItems().clear(); - comboBox.setConverter(new StringConverter() { - - @Override - public String toString(ConceptEntity conceptEntity) { - return getDisplayText(conceptEntity); - } - - @Override - public ConceptEntity fromString(String string) { - return null; - } - }); - - comboBox.setCellFactory(new Callback<>() { - - /** - * @param param The single argument upon which the returned value should be - * determined. - * @return - */ - @Override - public ListCell call(Object param) { - return new ListCell<>(){ - @Override - protected void updateItem(ConceptEntity conceptEntity, boolean b) { - super.updateItem(conceptEntity, b); - if (conceptEntity != null) { - setText(getDisplayText(conceptEntity)); - } else { - setText(null); - } - - } - }; - } - }); - comboBox.getItems().addAll(conceptEntities); - } - - private Optional findByNid(List items, int nid) { - - Optional conceptOption = items.stream().parallel() - .filter(item -> (item.nid() == nid)).findAny(); - - return conceptOption; - } - - public void setConceptAndPopulateForm(PublicId publicId) { - editDescrName = null; - this.publicId = publicId; - ViewCalculator viewCalculator = viewProperties.calculator(); - int nid = EntityService.get().nidForPublicId(publicId); - - // this is the Other Name - Latest latestEntityVersion = viewCalculator.latest(nid); - latestEntityVersion.ifPresent(semanticEntityVersion -> { - StampEntity stampEntity = latestEntityVersion.get().stamp(); - - // populate the other name text field (e.g. 'Chronic lung disease') - String otherName = viewCalculator.getDescriptionText(nid).get(); - this.otherNameTextField.setText(otherName); - - Entity moduleEntity = EntityService.get().getEntityFast(TinkarTerm.MODULE); - IntIdSet moduleDescendents = viewProperties.parentView().calculator().descendentsOf(moduleEntity.nid()); - - // get all descendant modules - Set allModules = - moduleDescendents.intStream() - .mapToObj(moduleNid -> (ConceptEntity) Entity.getFast(moduleNid)) - .collect(Collectors.toSet()); - setupComboBox(moduleComboBox, allModules); - - // populate the current module and select it (e.g. 'SNOMED CT core module') - findByNid(moduleComboBox.getItems(), stampEntity.moduleNid()) - .ifPresent(concept -> otherNameViewModel.setPropertyValue(MODULE, concept)); - - // get all statuses - IntIdSet statusDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.STATUS_VALUE.nid()); - Set allStatuses = statusDescendents.intStream() - .mapToObj(statusNid -> (ConceptEntity) Entity.getFast(statusNid)) - .collect(Collectors.toSet()); - setupComboBox(statusComboBox, allStatuses); - - // populate the current status (ACTIVE | INACTIVE) and select it - findByNid(statusComboBox.getItems(), stampEntity.stateNid()) - .ifPresent(concept -> otherNameViewModel.setPropertyValue(STATUS, concept)); - - // populate all case significance choices - IntIdSet caseSenseDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE.nid()); - Set allCaseDescendents = caseSenseDescendents.intStream() - .mapToObj(caseNid -> (ConceptEntity) Entity.getFast(caseNid)) - .collect(Collectors.toSet()); - setupComboBox(caseSignificanceComboBox, allCaseDescendents); - - // get case concept's case sensitivity (e.g. 'Case insensitive') - PatternEntity patternEntity = latestEntityVersion.get().pattern(); - PatternEntityVersion patternEntityVersion = viewCalculator.latest(patternEntity).get(); - int indexCaseSig = patternEntityVersion.indexForMeaning(DESCRIPTION_CASE_SIGNIFICANCE); - EntityFacade caseSigConceptFacade = (EntityFacade) latestEntityVersion.get().fieldValues().get(indexCaseSig); - findByNid(caseSignificanceComboBox.getItems(), caseSigConceptFacade.nid()) - .ifPresent(concept -> otherNameViewModel.setPropertyValue(CASE_SIGNIFICANCE, concept)); - - // get all available languages - IntIdSet languageDescendents = viewProperties.parentView().calculator().descendentsOf(TinkarTerm.LANGUAGE.nid()); - Set allLangs = languageDescendents.intStream() - .mapToObj(langNid -> (ConceptEntity) Entity.getFast(langNid)) - .collect(Collectors.toSet()); - setupComboBox(languageComboBox, allLangs); - - // get the language (e.g. 'English language') - int indexLang = patternEntityVersion.indexForMeaning(LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION); - ConceptFacade langConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexLang); - findByNid(languageComboBox.getItems(), langConceptFacade.nid()) - .ifPresent(concept -> otherNameViewModel.setPropertyValue(LANGUAGE, concept)); - - // get all descendant types - IntIdSet descriptionTypeDecendants = viewProperties.parentView().calculator().descendentsOf(DESCRIPTION_TYPE.nid()); - Set allDescritionTypes = - descriptionTypeDecendants.intStream() - .mapToObj(typeNid -> (ConceptEntity) Entity.getFast(typeNid)) - .collect(Collectors.toSet()); - setupComboBox(typeDisplayComboBox, allDescritionTypes); - //Set selected value for DESCRIPTION TYPE - int indexType = patternEntityVersion.indexForMeaning(DESCRIPTION_TYPE); - ConceptFacade typeConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexType); - findByNid(typeDisplayComboBox.getItems(), typeConceptFacade.nid()) - .ifPresent(concept -> otherNameViewModel.setPropertyValue(NAME_TYPE, concept)); - - //initial state of edit screen, the submit button should be disabled - submitButton.setDisable(true); - - LOG.info(publicId.toString()); - }); - } - - @FXML - private void updateOtherName(ActionEvent actionEvent) { - actionEvent.consume(); - otherNameViewModel.save(); - - if (!otherNameViewModel.hasNoErrorMsgs()) { - otherNameViewModel.getValidationMessages().stream().forEach(msg -> LOG.error("Validation error " + msg)); - return; - } - - otherNameViewModel.setPropertyValue(IS_SUBMITTED, true); - - - LOG.info("Ready to update to the concept view model: " + otherNameViewModel); - - if(this.publicId != null) { //This if blocked is called when editing the exiting concept. - otherNameViewModel.updateOtherName(this.publicId, viewProperties); - }else{ // This block is called when editing the while creating the concept. - otherNameViewModel.updateData(editDescrName); - eventBus.publish(conceptTopic, new CreateConceptEvent(this, - CreateConceptEvent.EDIT_OTHER_NAME, editDescrName)); - } - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - private DescrName editDescrName; - - /** - * This method prepopulates and sets up the form in edit mode. - * @param descrName model values that need to be prepopulated. - */ - public void setConceptAndPopulateForm(DescrName descrName) { - editDescrName = descrName; - setupComboBox(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); - setupComboBox(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.STATUS_VALUE.publicId())); - setupComboBox(caseSignificanceComboBox, otherNameViewModel.findAllCaseSignificants(getViewProperties())); - setupComboBox(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); - setupComboBox(typeDisplayComboBox, fetchDescendentsOfConcept(getViewProperties(), DESCRIPTION_TYPE.publicId())); - otherNameViewModel.setPropertyValue(NAME_TEXT, descrName.getNameText()) - .setPropertyValue(CASE_SIGNIFICANCE, descrName.getCaseSignificance()) - .setPropertyValue(STATUS, descrName.getStatus()) - .setPropertyValue(MODULE, descrName.getModule()) - .setPropertyValue(LANGUAGE, descrName.getLanguage()); - } - -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionsController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionsController.java deleted file mode 100644 index 33cffda4aa..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditDescriptionsController.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import dev.ikm.komet.kview.mvvm.view.BasicController; -import dev.ikm.komet.kview.events.AddOtherNameToConceptEvent; -import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; -import dev.ikm.komet.kview.events.EditConceptFullyQualifiedNameEvent; -import dev.ikm.komet.kview.events.OpenPropertiesPanelEvent; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.events.Subscriber; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.tinkar.common.id.PublicId; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.ObjectProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.UUID; - -public class EditDescriptionsController implements BasicController { - - private static final Logger LOG = LoggerFactory.getLogger(EditDescriptionsController.class); - - @FXML - private Button editFullyQualifiedNameButton; - - @FXML - private Button closePropertiesPanelButton; - - @FXML - private Button addOtherNameButton; - - private EvtBus eventBus; - - private UUID conceptTopic; - - private Subscriber propsPanelOpen; - - public EditDescriptionsController() {} - - public EditDescriptionsController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - private ObjectProperty fqnPublicId = new SimpleObjectProperty<>(); - - private ObjectProperty otherNamePublicId = new SimpleObjectProperty<>(); - - private ViewProperties viewProperties; - - @Override - @FXML - public void initialize() { - eventBus = EvtBusFactory.getDefaultEvtBus(); - - // when the user opens the properties panel, the edit fqn and add other name - // buttons should be able to populate their respective forms by passing the - // appropriate PublicId through the event bus - propsPanelOpen = evt -> { - fqnPublicId.set(evt.getFqnPublicId()); - }; - eventBus.subscribe(conceptTopic, OpenPropertiesPanelEvent.class, propsPanelOpen); - - editFullyQualifiedNameButton.setOnMouseClicked(event -> - eventBus.publish(conceptTopic, new EditConceptFullyQualifiedNameEvent(event, - EditConceptFullyQualifiedNameEvent.EDIT_FQN, fqnPublicId.get()))); - - closePropertiesPanelButton.setOnMouseClicked(event -> - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(event, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES))); - - addOtherNameButton.setOnMouseClicked(event -> - eventBus.publish(conceptTopic, new AddOtherNameToConceptEvent(event, - AddOtherNameToConceptEvent.ADD_DESCRIPTION, otherNamePublicId.get()))); - } - - - @Override - public void updateView() { - - } - - @Override - public void clearView() { - - } - - @Override - public void cleanup() { - - } - - public void updateModel(final ViewProperties viewProperties) { - this.viewProperties = viewProperties; - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditFullyQualifiedNameController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditFullyQualifiedNameController.java deleted file mode 100644 index bdda9fd5c0..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/EditFullyQualifiedNameController.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.IS_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TYPE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_CASE_SIGNIFICANCE; -import static dev.ikm.tinkar.terms.TinkarTerm.DESCRIPTION_TYPE; -import static dev.ikm.tinkar.terms.TinkarTerm.LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION; -import static dev.ikm.tinkar.terms.TinkarTerm.STATUS_VALUE; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.events.ClosePropertiesPanelEvent; -import dev.ikm.komet.kview.events.CreateConceptEvent; -import dev.ikm.komet.kview.events.EditConceptEvent; -import dev.ikm.komet.kview.mvvm.model.DescrName; -import dev.ikm.komet.kview.mvvm.view.BasicController; -import dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel; -import dev.ikm.tinkar.common.id.PublicId; -import dev.ikm.tinkar.coordinate.stamp.calculator.Latest; -import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator; -import dev.ikm.tinkar.entity.ConceptEntity; -import dev.ikm.tinkar.entity.Entity; -import dev.ikm.tinkar.entity.EntityService; -import dev.ikm.tinkar.entity.EntityVersion; -import dev.ikm.tinkar.entity.PatternEntity; -import dev.ikm.tinkar.entity.PatternEntityVersion; -import dev.ikm.tinkar.entity.SemanticEntityVersion; -import dev.ikm.tinkar.entity.StampEntity; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.terms.ConceptFacade; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.beans.InvalidationListener; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.TextField; -import javafx.util.Callback; -import javafx.util.StringConverter; -import org.carlfx.cognitive.loader.InjectViewModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -public class EditFullyQualifiedNameController implements BasicController { - - private static final Logger LOG = LoggerFactory.getLogger(EditFullyQualifiedNameController.class); - - private UUID conceptTopic; - - private ViewProperties viewProperties; - - private EntityFacade entityFacade; - - private PublicId publicId; - - @FXML - private Label editFullyQualifiedNameTitleLabel; - - @FXML - private TextField fqnText; - - @FXML - private ComboBox typeDisplayComboBox; - - @FXML - private ComboBox moduleComboBox; - - @FXML - private ComboBox statusComboBox; - - @FXML - private ComboBox caseSignificanceComboBox; - - @FXML - private ComboBox languageComboBox; - - @FXML - private Label dialect1Label; - - @FXML - private Label dialect2Label; - - @FXML - private Label dialect3Label; - - @FXML - private ComboBox dialectComboBox1; - - @FXML - private ComboBox dialectComboBox2; - - @FXML - private ComboBox dialectComboBox3; - - @FXML - private Button submitButton; - - @FXML - private Button cancelButton; - - private EvtBus eventBus; - - @InjectViewModel - private DescrNameViewModel fqnViewModel; - - public EditFullyQualifiedNameController() { } - - public EditFullyQualifiedNameController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - @FXML - public void initialize() { - eventBus = EvtBusFactory.getDefaultEvtBus(); - clearView(); - setEditFullyQualifiedNameTitleLabel("Edit Description: Fully Qualified Name"); - populateDialectComboBoxes(); - - fqnViewModel.setPropertyValue(NAME_TYPE, TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE); - - // bind with viewmodel. - fqnText.textProperty().bindBidirectional(fqnViewModel.getProperty(NAME_TEXT)); - moduleComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(MODULE)); - caseSignificanceComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(CASE_SIGNIFICANCE)); - statusComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(STATUS)); - languageComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(LANGUAGE)); - typeDisplayComboBox.valueProperty().bindBidirectional(fqnViewModel.getProperty(NAME_TYPE)); - - InvalidationListener invalidationListener = obs -> validateForm(); - - fqnText.textProperty().addListener(invalidationListener); - moduleComboBox.valueProperty().addListener(invalidationListener); - caseSignificanceComboBox.valueProperty().addListener(invalidationListener); - statusComboBox.valueProperty().addListener(invalidationListener); - languageComboBox.valueProperty().addListener(invalidationListener); - typeDisplayComboBox.valueProperty().addListener(invalidationListener); - - validateForm(); - submitButton.setOnAction(this::updateFQN); - - } - - @FXML - private void handleCancelButtonEvent() { - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(cancelButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - private void validateForm() { - boolean isFqnTextEmpty = fqnText.getText().trim().isEmpty(); - boolean isModuleComboBoxSelected = moduleComboBox.getValue() != null; - boolean isCaseSignificanceComboBoxSelected = caseSignificanceComboBox.getValue() != null; - boolean isStatusComboBoxComboBoxSelected = statusComboBox.getValue() != null; - boolean isLanguageComboBoxComboBoxSelected = languageComboBox.getValue() != null; - - submitButton.setDisable( - isFqnTextEmpty || !isModuleComboBoxSelected - || !isCaseSignificanceComboBoxSelected || !isLanguageComboBoxComboBoxSelected - || !isStatusComboBoxComboBoxSelected); - } - - private void populateDialectComboBoxes() { - // currently no UNACCEPTABLE in TinkarTerm - Entity acceptable = EntityService.get().getEntityFast(TinkarTerm.ACCEPTABLE); - Entity preferred = EntityService.get().getEntityFast(TinkarTerm.PREFERRED); - - // each combo box has a separate list instance - setupComboBox(dialectComboBox1, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox1.getSelectionModel().select(Entity.getFast(acceptable.nid())); - setupComboBox(dialectComboBox2, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox2.getSelectionModel().select(Entity.getFast(preferred.nid())); - setupComboBox(dialectComboBox3, Arrays.asList(Entity.getFast(acceptable.nid()), Entity.getFast(preferred.nid()))); - dialectComboBox3.getSelectionModel().select(Entity.getFast(preferred.nid())); - } - - public void setEditFullyQualifiedNameTitleLabel(String editFullyQualifiedNameTitleLabel) { - this.editFullyQualifiedNameTitleLabel.setText(editFullyQualifiedNameTitleLabel); - } - - public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade) { - this.viewProperties = viewProperties; - this.entityFacade = entityFacade; - } - - private ViewProperties getViewProperties() { - return this.viewProperties; - } - - private String getDisplayText(ConceptEntity conceptEntity) { - if (conceptEntity != null) { - Optional stringOptional = getViewProperties().calculator().languageCalculator().getRegularDescriptionText(conceptEntity.nid()); - return stringOptional.orElse(""); - } else { - return ""; - } - } - - private void setupComboBox(ComboBox comboBox, Collection conceptEntities) { - comboBox.getItems().clear(); - comboBox.setConverter(new StringConverter() { - - @Override - public String toString(ConceptEntity conceptEntity) { - return getDisplayText(conceptEntity); - } - - @Override - public ConceptEntity fromString(String string) { - return null; - } - }); - - comboBox.setCellFactory(new Callback<>() { - - /** - * @param param The single argument upon which the returned value should be - * determined. - * @return - */ - @Override - public ListCell call(Object param) { - return new ListCell<>(){ - @Override - protected void updateItem(ConceptEntity conceptEntity, boolean b) { - super.updateItem(conceptEntity, b); - if (conceptEntity != null) { - setText(getDisplayText(conceptEntity)); - } else { - setText(null); - } - - } - }; - } - }); - comboBox.getItems().addAll(conceptEntities); - } - - public void setConceptAndPopulateForm(PublicId publicId) { - this.publicId = publicId; - - ViewCalculator viewCalculator = viewProperties.calculator(); - - int nid = EntityService.get().nidForPublicId(publicId); - - // this is the Other Name - Latest latestEntityVersion = viewCalculator.latest(nid); - latestEntityVersion.ifPresent(semanticEntityVersion -> { - StampEntity stampEntity = latestEntityVersion.get().stamp(); - String fullyQualifiedName = viewCalculator.getDescriptionText(nid).get(); - this.fqnText.setText(fullyQualifiedName); - - // get all descendant modules - setupComboBox(moduleComboBox, fetchDescendentsOfConcept(viewProperties,TinkarTerm.MODULE.publicId())); - - // populate the current module and select it (e.g. 'SNOMED CT core module') - findByNid(moduleComboBox.getItems(), stampEntity.moduleNid()) - .ifPresent(concept -> fqnViewModel.setPropertyValue(MODULE, concept)); - - // get all statuses - setupComboBox(statusComboBox, fetchDescendentsOfConcept(viewProperties,STATUS_VALUE.publicId())); - - // populate the current status (ACTIVE | INACTIVE) and select it - findByNid(statusComboBox.getItems(), stampEntity.stateNid()) - .ifPresent(concept -> fqnViewModel.setPropertyValue(STATUS, concept)); - - - // populate all case significance choices - setupComboBox(caseSignificanceComboBox, fetchDescendentsOfConcept(viewProperties,DESCRIPTION_CASE_SIGNIFICANCE.publicId())); - - // get case concept's case sensitivity (e.g. 'Case insensitive') - PatternEntity patternEntity = latestEntityVersion.get().pattern(); - PatternEntityVersion patternEntityVersion = viewCalculator.latest(patternEntity).get(); - - int indexCaseSig = patternEntityVersion.indexForMeaning(DESCRIPTION_CASE_SIGNIFICANCE); - ConceptFacade caseSigConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexCaseSig); - findByNid(caseSignificanceComboBox.getItems(), caseSigConceptFacade.nid()) - .ifPresent(concept -> fqnViewModel.setPropertyValue(CASE_SIGNIFICANCE, concept)); - - - // get all available languages - setupComboBox(languageComboBox, fetchDescendentsOfConcept(viewProperties, TinkarTerm.LANGUAGE.publicId())); - // get the language (e.g. 'English language') - int indexLang = patternEntityVersion.indexForMeaning(LANGUAGE_CONCEPT_NID_FOR_DESCRIPTION); - ConceptFacade langConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexLang); - findByNid(languageComboBox.getItems(), langConceptFacade.nid()) - .ifPresent(concept -> fqnViewModel.setPropertyValue(LANGUAGE, concept)); - - // get all descendant types - setupComboBox(typeDisplayComboBox, fetchDescendentsOfConcept(viewProperties, DESCRIPTION_TYPE.publicId())); - //Set selected value for DESCRIPTION TYPE - int indexType = patternEntityVersion.indexForMeaning(DESCRIPTION_TYPE); - ConceptFacade typeConceptFacade = (ConceptFacade) latestEntityVersion.get().fieldValues().get(indexType); - findByNid(typeDisplayComboBox.getItems(), typeConceptFacade.nid()) - .ifPresent(concept -> fqnViewModel.setPropertyValue(NAME_TYPE, concept)); - - //initial state of edit screen, the submit button should be disabled - submitButton.setDisable(true); - - LOG.info(publicId.toString()); - - }); - } - - @FXML - private void updateFQN(ActionEvent actionEvent) { - actionEvent.consume(); - - fqnViewModel.save(); - // validate - if (fqnViewModel.hasErrorMsgs()) { - fqnViewModel.getValidationMessages().stream().forEach(msg -> LOG.error("Validation error " + msg)); - return; - } - fqnViewModel.setPropertyValue(IS_SUBMITTED, true); - - DescrName fqnDescrName = fqnViewModel.create(); - - - if(this.publicId != null) { - // delegate the transaction logic to the view model - fqnViewModel.updateFullyQualifiedName(this.publicId, getViewProperties()); - }else{ - // Concept is edited before the transaction is saved. Hence the pubicId would not be generated. - eventBus.publish(conceptTopic, new CreateConceptEvent(this, CreateConceptEvent.ADD_FQN, fqnDescrName)); - } - - LOG.info("transaction complete"); - clearView(); - - // publish the event of the updated FQN - eventBus.publish(conceptTopic, new EditConceptEvent(submitButton, - EditConceptEvent.EDIT_FQN, fqnDescrName)); - - // close the property bump out panel - eventBus.publish(conceptTopic, new ClosePropertiesPanelEvent(submitButton, - ClosePropertiesPanelEvent.CLOSE_PROPERTIES)); - } - - - @Override - public void updateView() { } - - @Override - public void clearView() { - fqnText.setText(""); - caseSignificanceComboBox.getSelectionModel().clearSelection(); - statusComboBox.getSelectionModel().clearSelection(); - moduleComboBox.getSelectionModel().clearSelection(); - languageComboBox.getSelectionModel().clearSelection(); - } - - @Override - public void cleanup() { } - - private Optional findByNid(List items, int nid) { - - Optional conceptOption = items.stream().parallel() - .filter(item -> (item.nid() == nid)).findAny(); - - return conceptOption; - } - - /** - * This method prepopulates and sets up the form in edit mode. - * @param descrName model values that need to be prepopulated. - */ - public void setConceptAndPopulateForm(DescrName descrName) { - setupComboBox(moduleComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.MODULE.publicId())); - setupComboBox(statusComboBox, fetchDescendentsOfConcept(getViewProperties(), STATUS_VALUE.publicId())); - setupComboBox(caseSignificanceComboBox, fqnViewModel.findAllCaseSignificants(getViewProperties())); - setupComboBox(languageComboBox, fetchDescendentsOfConcept(getViewProperties(), TinkarTerm.LANGUAGE.publicId())); - setupComboBox(typeDisplayComboBox, fetchDescendentsOfConcept(getViewProperties(), DESCRIPTION_TYPE.publicId())); - fqnViewModel.setPropertyValue(NAME_TEXT, descrName.getNameText()) - .setPropertyValue(CASE_SIGNIFICANCE, descrName.getCaseSignificance()) - .setPropertyValue(STATUS, descrName.getStatus()) - .setPropertyValue(MODULE, descrName.getModule()) - .setPropertyValue(LANGUAGE, descrName.getLanguage()) - .setPropertyValue(NAME_TYPE, descrName.getNameType()); - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/HistoryChangeController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/HistoryChangeController.java index 6fb101c040..675761e30a 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/HistoryChangeController.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/HistoryChangeController.java @@ -51,6 +51,9 @@ */ public class HistoryChangeController implements BasicController { private static final Logger LOG = LoggerFactory.getLogger(HistoryChangeController.class); + + public static final String HISTORY_CHANGE_FXML_FILE = "history-change-selection.fxml"; + protected static final String DESCRIPTION_LIST_ITEM_FXML_FILE = "change-list-item.fxml"; @FXML private ChoiceBox changeFilterChoiceBox; diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java deleted file mode 100644 index 5a14044de1..0000000000 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/view/properties/PropertiesController.java +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dev.ikm.komet.kview.mvvm.view.properties; - -import static dev.ikm.komet.kview.events.StampEvent.ADD_STAMP; -import static dev.ikm.komet.kview.events.StampEvent.CREATE_STAMP; -import static dev.ikm.komet.kview.fxutils.CssHelper.genText; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.IS_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.MODULE; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.NAME_TEXT; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.PARENT_PUBLIC_ID; -import static dev.ikm.komet.kview.mvvm.viewmodel.DescrNameViewModel.STATUS; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.DESCRIPTION_CASE_SIGNIFICANCE; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.DESCRIPTION_LANGUAGE; -import static dev.ikm.komet.kview.mvvm.viewmodel.OtherNameViewModel.OtherNameProperties.HAS_OTHER_NAME; -import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Type.CONCEPT; -import dev.ikm.komet.framework.view.ViewProperties; -import dev.ikm.komet.kview.mvvm.view.common.StampFormController; -import dev.ikm.komet.kview.events.AddFullyQualifiedNameEvent; -import dev.ikm.komet.kview.events.AddOtherNameToConceptEvent; -import dev.ikm.komet.kview.events.EditConceptFullyQualifiedNameEvent; -import dev.ikm.komet.kview.events.EditOtherNameConceptEvent; -import dev.ikm.komet.kview.events.OpenPropertiesPanelEvent; -import dev.ikm.komet.kview.events.ShowEditDescriptionPanelEvent; -import dev.ikm.komet.kview.events.StampEvent; -import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampAddSubmitFormViewModel; -import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampCreateFormViewModel; -import dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase; -import dev.ikm.tinkar.common.id.PublicId; -import dev.ikm.tinkar.events.EvtBus; -import dev.ikm.tinkar.events.EvtBusFactory; -import dev.ikm.tinkar.events.Subscriber; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.scene.control.Toggle; -import javafx.scene.control.ToggleButton; -import javafx.scene.control.ToggleGroup; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.FlowPane; -import javafx.scene.layout.Pane; -import javafx.scene.layout.StackPane; -import javafx.scene.shape.SVGPath; -import org.carlfx.cognitive.loader.Config; -import org.carlfx.cognitive.loader.FXMLMvvmLoader; -import org.carlfx.cognitive.loader.JFXNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.util.UUID; - -/** - * The properties window providing tabs of Edit, Hierarchy, History, and Comments. - * This view is associated with the view file history-change-selection.fxml. - */ -public class PropertiesController implements Serializable { - private static final Logger LOG = LoggerFactory.getLogger(PropertiesController.class); - - protected static final String HISTORY_CHANGE_FXML_FILE = "history-change-selection.fxml"; - protected static final String HIERARCHY_VIEW_FXML_FILE = "hierarchy-view.fxml"; - - protected static final String EDIT_VIEW_FXML_FILE = "edit-view.fxml"; - - protected static final String EDIT_DESCRIPTIONS_FXML_FILE = "edit-descriptions.fxml"; - - protected static final String ADD_OTHER_NAME_FXML_FILE = "add-other-name.fxml"; - - protected static final String EDIT_OTHER_NAME_FXML_FILE = "edit-other-name-form.fxml"; - - protected static final String EDIT_FQN_FXML_FILE = "edit-fully-qualified-name.fxml"; - - protected static final String ADD_FQN_FXML_FILE = "add-fully-qualified-name.fxml"; - - @FXML - private ToggleButton commentsButton; - - @FXML - private ToggleButton editButton; - - @FXML - private ToggleButton historyButton; - - @FXML - private ToggleButton hierarchyButton; - - @FXML - private ToggleGroup propertyToggleButtonGroup; - - @FXML - private BorderPane contentBorderPane; - - @FXML - private FlowPane propertiesTabsPane; - - private JFXNode stampJFXNode; - private Pane historyTabsBorderPane; - private HistoryChangeController historyChangeController; - - private Pane hierarchyTabBorderPane; - private HierarchyController hierarchyController; - - private Pane editBorderPane; - - private Pane addOtherNamePane; - - private Pane editFqnPane; - - private Pane addFqnPane; - - private Pane editDescriptionsPane; - - private Pane editOtherNamePane; - - private EditConceptController editConceptController; - - private AddOtherNameController addOtherNameController; - - private EditDescriptionFormController editDescriptionFormController; - - private EditDescriptionsController editDescriptionsController; - - private EditFullyQualifiedNameController editFullyQualifiedNameController; - - private AddFullyQualifiedNameController addFullyQualifiedNameController; - - private Pane commentsPane = new StackPane(genText("Comments Pane")); - private ViewProperties viewProperties; - private EntityFacade entityFacade; - - private PublicId fqnPublicId; - - private PublicId otherNamePublicId; // latest other name - - private EvtBus eventBus; - - private Subscriber addOtherNameSubscriber; - - private Subscriber editOtherNameConceptEventSubscriber; - - private Subscriber editConceptFullyQualifiedNameEventSubscriber; - - private Subscriber addFqnSubscriber; - - private Subscriber editDescriptionPaneSubscriber; - - private Subscriber addStampSubscriber; - - private Subscriber createStampSubscriber; - - private Subscriber propsPanelOpen; - - - private UUID conceptTopic; - - private boolean hasOtherNames = false; - - private StampAddSubmitFormViewModel stampAddSubmitFormViewModel; - - private StampCreateFormViewModel stampCreateFormViewModel; - - private boolean editMode; - - public PropertiesController() { - } - - public PropertiesController(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - this.stampAddSubmitFormViewModel = new StampAddSubmitFormViewModel(CONCEPT); - this.stampCreateFormViewModel = new StampCreateFormViewModel(CONCEPT); - } - - /** - * This is called after dependency injection has occurred to the JavaFX controls above. - */ - @FXML - public void initialize() throws IOException { - clearView(); - - eventBus = EvtBusFactory.getDefaultEvtBus(); - - // Load Stamp add View Panel (FXML & Controller) - Config stampConfig = new Config(StampFormController.class.getResource(StampFormController.STAMP_FORM_FXML_FILE)); - stampJFXNode = FXMLMvvmLoader.make(stampConfig); - - // Load History tabs View Panel (FXML & Controller) - FXMLLoader loader = new FXMLLoader(getClass().getResource(HISTORY_CHANGE_FXML_FILE)); - historyTabsBorderPane = loader.load(); - historyChangeController = loader.getController(); - - // Load Hierarchy tab View Panel (FXML & Controller) - FXMLLoader loader2 = new FXMLLoader(getClass().getResource(HIERARCHY_VIEW_FXML_FILE)); - hierarchyTabBorderPane = loader2.load(); - hierarchyController = loader2.getController(); - - // Load Edit tab - FXMLLoader loaderEdit = new FXMLLoader(getClass().getResource(EDIT_VIEW_FXML_FILE)); - loaderEdit.setController(new EditConceptController(conceptTopic)); - editBorderPane = loaderEdit.load(); - editConceptController = loaderEdit.getController(); - - // Edit Descriptions panel inside the Edit tab (under Properties bump out on Concept window) - FXMLLoader loaderEditDescriptions = new FXMLLoader(getClass().getResource(EDIT_DESCRIPTIONS_FXML_FILE)); - loaderEditDescriptions.setController(new EditDescriptionsController(conceptTopic)); - editDescriptionsPane = loaderEditDescriptions.load(); - editDescriptionsController = loaderEditDescriptions.getController(); - - // NOTE: New way of using injected View Models inside of Controllers. - JFXNode addOtherNameControllerNode = FXMLMvvmLoader.make( - getClass().getResource(ADD_OTHER_NAME_FXML_FILE), - new AddOtherNameController(conceptTopic)); - - addOtherNamePane = addOtherNameControllerNode.node(); - addOtherNameController = addOtherNameControllerNode.controller(); - - JFXNode editDescriptionFormControllerNode = FXMLMvvmLoader.make( - getClass().getResource(EDIT_OTHER_NAME_FXML_FILE), - new EditDescriptionFormController(conceptTopic)); - editOtherNamePane = editDescriptionFormControllerNode.node(); - editDescriptionFormController = editDescriptionFormControllerNode.controller(); - - //TODO for future there will be an edit axiom form - - JFXNode editFqnControllerNode = FXMLMvvmLoader.make( - getClass().getResource(EDIT_FQN_FXML_FILE), - new EditFullyQualifiedNameController(conceptTopic) - ); - editFqnPane = editFqnControllerNode.node(); - editFullyQualifiedNameController = editFqnControllerNode.controller(); - - // NOTE: New way of using injected View Models inside of Controllers. - JFXNode addFqnControllerNode = FXMLMvvmLoader.make( - getClass().getResource(ADD_FQN_FXML_FILE), - new AddFullyQualifiedNameController(conceptTopic)); - addFqnPane = addFqnControllerNode.node(); - addFullyQualifiedNameController = addFqnControllerNode.controller(); - - // initially a default selected tab and view is shown - updateDefaultSelectedViews(); - - // when we receive an event because the user clicked the - // Edit Descriptions Button - // we then load the panel with the choice of buttons to edit - editDescriptionPaneSubscriber = evt -> contentBorderPane.setCenter(editDescriptionsPane); - eventBus.subscribe(conceptTopic, ShowEditDescriptionPanelEvent.class, editDescriptionPaneSubscriber); - - - // when we receive an event because the user clicked the - // Add Other Name button from the Properties > Edit bump out, we want to change the Pane in the - // Edit Concept bump out to be the Add Other Name form - addOtherNameSubscriber = evt -> { - // check if the center pane is already showing, we don't want duplicate entries in the dropdowns - if (!contentBorderPane.getCenter().equals(addOtherNamePane)) { - contentBorderPane.setCenter(addOtherNamePane); - editButton.setSelected(true); - editButton.setText("ADD"); - - // Create a new View Model for this form - addOtherNameController.updateModel(getViewProperties(), (viewModel, controller) -> { - // Clear view model. Please see addOtherNameController's initialize() method. - viewModel.setValue(NAME_TEXT, "") - .setValue(CASE_SIGNIFICANCE, null) - .setValue(MODULE, null) - .setValue(LANGUAGE, null) - .setValue(STATUS, TinkarTerm.ACTIVE_STATE) - .setValue(IS_SUBMITTED, false) - - .setValue(DESCRIPTION_CASE_SIGNIFICANCE, addFullyQualifiedNameController.getViewModel().getValue(CASE_SIGNIFICANCE)) - .setValue(DESCRIPTION_LANGUAGE, addFullyQualifiedNameController.getViewModel().getValue(LANGUAGE)) - - .setValue(HAS_OTHER_NAME, hasOtherNames); - - // if in edit mode and navigating from the properties > edit > add other name - // then the public id will be set - if (evt.getPublicId() != null) { - viewModel.setValue(PARENT_PUBLIC_ID, evt.getPublicId()); - } - viewModel.reset(); // copy model values into property values - // update the UI form - controller.clearView(); - controller.updateView(); - }); - } - }; - eventBus.subscribe(conceptTopic, AddOtherNameToConceptEvent.class, addOtherNameSubscriber); - - // when we receive an event because the user clicked the - // Add Axiom button, we want to change the Pane in the - // Edit Concept bump out to be the Add Axiom form - - editOtherNameConceptEventSubscriber = evt -> { - contentBorderPane.setCenter(editOtherNamePane); - editButton.setSelected(true); - editButton.setText("EDIT"); - if (evt.getPublicId() != null) { - editDescriptionFormController.setConceptAndPopulateForm(evt.getPublicId()); - }else { - editDescriptionFormController.setConceptAndPopulateForm(evt.getDescrName()); - } - }; - eventBus.subscribe(conceptTopic, EditOtherNameConceptEvent.class, editOtherNameConceptEventSubscriber); - - - // when we receive an event because the user clicked the - // Fully Qualified Name in the Concept, we want to change the Pane in the - // Edit Concept bump out to be the Edit Fully Qualified Name form - editConceptFullyQualifiedNameEventSubscriber = evt -> { - // don't go into edit mode if there is no FQN yet - if (evt.getPublicId() == null && evt.getDescrName() == null) { - // default to adding an FQN is there isn't one - eventBus.publish(conceptTopic, new AddFullyQualifiedNameEvent(evt, - AddFullyQualifiedNameEvent.ADD_FQN, getViewProperties())); - return; - } - // check if the center pane is already showing, we don't want duplicate entries in the dropdowns - if (!contentBorderPane.getCenter().equals(editFqnPane)) { - editFullyQualifiedNameController.updateModel(getViewProperties(), null); - contentBorderPane.setCenter(editFqnPane); - } - editButton.setSelected(true); - editButton.setText("EDIT"); - if (evt.getPublicId() != null) { - editFullyQualifiedNameController.setConceptAndPopulateForm(evt.getPublicId()); - }else { - editFullyQualifiedNameController.setConceptAndPopulateForm(evt.getDescrName()); - } - }; - eventBus.subscribe(conceptTopic, EditConceptFullyQualifiedNameEvent.class, editConceptFullyQualifiedNameEventSubscriber); - - // this event happens on during the creation of a new concept - // a new concept will not have a fully qualified name and will need one - addFqnSubscriber = evt -> { - // check if the center pane is already showing, we don't want duplicate entries in the dropdowns - if (!contentBorderPane.getCenter().equals(addFqnPane)) { - contentBorderPane.setCenter(addFqnPane); - editButton.setSelected(true); - editButton.setText("ADD"); - - // Clear existing ViewModel in form. - addFullyQualifiedNameController.updateModel(evt.getViewProperties(), (viewModel, controller) -> { - viewModel.setPropertyValue(NAME_TEXT, "") - .setPropertyValue(CASE_SIGNIFICANCE, null) - .setPropertyValue(MODULE, null) - .setPropertyValue(LANGUAGE, null) - .setPropertyValue(STATUS, TinkarTerm.ACTIVE_STATE) - .setPropertyValue(IS_SUBMITTED, false); - controller.clearView(); - controller.updateView(); - }); - } - }; - eventBus.subscribe(conceptTopic, AddFullyQualifiedNameEvent.class, addFqnSubscriber); - - // when opening the properties panel the default toggle to view is the history tab - propsPanelOpen = evt -> { - if (contentBorderPane.getCenter() == null) { - historyButton.setSelected(true); - contentBorderPane.setCenter(historyTabsBorderPane); - } - }; - eventBus.subscribe(conceptTopic, OpenPropertiesPanelEvent.class, propsPanelOpen); - - // -- add stamp - addStampSubscriber = evt -> { - if (evt.getEventType() == ADD_STAMP) { - stampJFXNode.controller().init(stampAddSubmitFormViewModel); - this.stampAddSubmitFormViewModel.update(entityFacade, conceptTopic, viewProperties); - - contentBorderPane.setCenter(stampJFXNode.node()); - editButton.setSelected(true); - } - }; - - eventBus.subscribe(conceptTopic, StampEvent.class, addStampSubscriber); - - // -- create stamp - createStampSubscriber = evt -> { - if (evt.getEventType() == CREATE_STAMP) { - stampJFXNode.controller().init(stampCreateFormViewModel); - this.stampCreateFormViewModel.update(entityFacade, conceptTopic, viewProperties); - - contentBorderPane.setCenter(stampJFXNode.node()); - editButton.setSelected(true); - } - }; - - eventBus.subscribe(conceptTopic, StampEvent.class, createStampSubscriber); - } - - public ViewProperties getViewProperties() { - return viewProperties; - } - - public void setConceptTopic(UUID conceptTopic) { - this.conceptTopic = conceptTopic; - } - - private void updateDefaultSelectedViews() { - // default to selected tab (History) - Toggle tab = propertyToggleButtonGroup.getSelectedToggle(); - if (editButton.equals(tab)) { - contentBorderPane.setCenter(editBorderPane); - } else if (hierarchyButton.equals(tab)) { - contentBorderPane.setCenter(hierarchyTabBorderPane); - } else if (historyButton.equals(tab)) { - contentBorderPane.setCenter(historyTabsBorderPane); - } else if (commentsButton.equals(tab)) { - contentBorderPane.setCenter(commentsPane); - } - } - - public String selectedView() { - Toggle tab = propertyToggleButtonGroup.getSelectedToggle(); - if (editButton.equals(tab)) { - return "EDIT"; - } else if (hierarchyButton.equals(tab)) { - return "HIERARCHY"; - } else if (historyButton.equals(tab)) { - return "HISTORY"; - } else if (commentsButton.equals(tab)) { - return "COMMENTS"; - } else { - return "NONE"; - } - }; - - public void restoreSelectedView(String selectedView) { - LOG.info("restore selected concept view with " + selectedView); - switch (selectedView) { - case "EDIT" -> { - editButton.setSelected(true); - contentBorderPane.setCenter(editBorderPane); - } - case "HIERARCHY" -> { - hierarchyButton.setSelected(true); - contentBorderPane.setCenter(hierarchyTabBorderPane); - } - case "HISTORY" -> { - historyButton.setSelected(true); - contentBorderPane.setCenter(historyTabsBorderPane); - } - case "COMMENTS" -> { - commentsButton.setSelected(true); - contentBorderPane.setCenter(commentsPane); - } - } - } - - public void updateModel(final ViewProperties viewProperties, EntityFacade entityFacade){ - this.viewProperties = viewProperties; - this.entityFacade = entityFacade; - this.historyChangeController.updateModel(viewProperties, entityFacade); - this.hierarchyController.updateModel(viewProperties, entityFacade); - - this.editDescriptionsController.updateModel(viewProperties); - - this.editDescriptionFormController.updateModel(viewProperties, entityFacade); - this.editFullyQualifiedNameController.updateModel(viewProperties, entityFacade); - - // Create a new DescrNameViewModel for the otherNameViewModel. - this.addOtherNameController.updateModel(viewProperties); - - // Create a new DescrNameViewModel for the addfqncontroller. - this.addFullyQualifiedNameController.updateModel(viewProperties); - - if (editMode && stampAddSubmitFormViewModel != null) { - this.stampAddSubmitFormViewModel.update(entityFacade, conceptTopic, viewProperties); - } else if (!editMode && stampCreateFormViewModel != null) { - this.stampCreateFormViewModel.update(entityFacade, conceptTopic, viewProperties); - } - } - - public void updateView() { - this.historyChangeController.updateView(); - this.hierarchyController.updateView(); - } - - @FXML - private void showEditView(ActionEvent event) { - event.consume(); - this.editButton.setSelected(true); - LOG.info("Show Edit View " + event); - contentBorderPane.setCenter(editBorderPane); - } - @FXML - private void showNavigatorView(ActionEvent event) { - event.consume(); - LOG.info("Show Navigator View " + event); - contentBorderPane.setCenter(hierarchyTabBorderPane); - } - @FXML - private void showHistoryView(ActionEvent event) { - event.consume(); - LOG.info("Show History View " + event); - contentBorderPane.setCenter(historyTabsBorderPane); - } - @FXML - private void showCommentsView(ActionEvent event) { - event.consume(); - LOG.info("Show Comments View " + event); - contentBorderPane.setCenter(commentsPane); - - } - - public HistoryChangeController getHistoryChangeController() { - return historyChangeController; - } - - public HierarchyController getHierarchyController() { - return hierarchyController; - } - - public void clearView() { - } - - /** - * Returns the propertiesTabsPane to be used as a draggable region. - * @return The FlowPane containing the property tabs - */ - public FlowPane getPropertiesTabsPane() { - return propertiesTabsPane; - } - - public void setHasOtherName(boolean value) { - hasOtherNames = value; - } - - public void setEditMode(boolean editMode) { - this.editMode = editMode; - } - - public StampFormViewModelBase getStampFormViewModel() { - if (editMode) { - return stampAddSubmitFormViewModel; - } else { - return stampCreateFormViewModel; - } - } -} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModel.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModelNext.java similarity index 61% rename from kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModel.java rename to kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModelNext.java index a9a8c4362d..7d4c0cb237 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModel.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/ConceptViewModelNext.java @@ -1,24 +1,5 @@ -/* - * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package dev.ikm.komet.kview.mvvm.viewmodel; -import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.IS_CONFIRMED_OR_SUBMITTED; -import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.STATUS; -import static dev.ikm.tinkar.coordinate.stamp.StampFields.MODULE; -import static dev.ikm.tinkar.coordinate.stamp.StampFields.PATH; import dev.ikm.komet.framework.builder.AxiomBuilderRecord; import dev.ikm.komet.framework.builder.ConceptEntityBuilder; import dev.ikm.komet.framework.view.ViewProperties; @@ -29,30 +10,13 @@ import dev.ikm.tinkar.common.id.PublicId; import dev.ikm.tinkar.common.id.PublicIds; import dev.ikm.tinkar.common.service.TinkExecutor; -import dev.ikm.tinkar.coordinate.edit.EditCoordinateRecord; -import dev.ikm.tinkar.entity.ConceptEntity; -import dev.ikm.tinkar.entity.ConceptRecord; -import dev.ikm.tinkar.entity.Entity; -import dev.ikm.tinkar.entity.EntityService; -import dev.ikm.tinkar.entity.RecordListBuilder; -import dev.ikm.tinkar.entity.SemanticRecord; -import dev.ikm.tinkar.entity.SemanticRecordBuilder; -import dev.ikm.tinkar.entity.SemanticVersionRecordBuilder; -import dev.ikm.tinkar.entity.StampEntity; +import dev.ikm.tinkar.entity.*; import dev.ikm.tinkar.entity.graph.DiTreeEntity; import dev.ikm.tinkar.entity.graph.EntityVertex; import dev.ikm.tinkar.entity.transaction.CommitTransactionTask; import dev.ikm.tinkar.entity.transaction.Transaction; -import dev.ikm.tinkar.terms.ConceptFacade; -import dev.ikm.tinkar.terms.EntityFacade; -import dev.ikm.tinkar.terms.EntityProxy; -import dev.ikm.tinkar.terms.State; -import dev.ikm.tinkar.terms.TinkarTerm; -import javafx.beans.property.ReadOnlyStringProperty; -import javafx.collections.ObservableList; -import org.carlfx.cognitive.validator.MessageType; -import org.carlfx.cognitive.validator.ValidationMessage; -import org.carlfx.cognitive.viewmodel.ViewModel; +import dev.ikm.tinkar.terms.*; +import org.carlfx.cognitive.viewmodel.SimpleViewModel; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.list.ImmutableList; import org.eclipse.collections.api.list.MutableList; @@ -60,60 +24,132 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; -public class ConceptViewModel extends FormViewModel { - private static final Logger LOG = LoggerFactory.getLogger(ConceptViewModel.class); +import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.IS_CONFIRMED_OR_SUBMITTED; +import static dev.ikm.komet.kview.mvvm.viewmodel.stamp.StampFormViewModelBase.Properties.STATUS; +import static dev.ikm.tinkar.coordinate.stamp.StampFields.MODULE; +import static dev.ikm.tinkar.coordinate.stamp.StampFields.PATH; + +public class ConceptViewModelNext extends SimpleViewModel { + private static final Logger LOG = LoggerFactory.getLogger(ConceptViewModelNext.class); + + /// ViewModel Property Keys + public enum ConceptPropertyKeys { + /// A newly added concept does not have a nid at the start. + /// + /// If new concept (true) we commit every associated created + /// semantics ( e.g fqn / otherNames) in one go with the "same" stamp that we commit the concept for. This + /// happens currently when the user adds a Axiom. + /// + /// Its also crucial that we first create a ValidStamp, because than we can create a initial stamp record and then + /// use the then created ConceptEntity facades nid to create an set of Semantic NameDescription. Without a Concept + /// Semantic descriptions would not know where to point to. E.g the problem would be that a new Semantic Description + /// would not know what type fields it should provide (language, case_significance, modules etc) for selection as this is depending on the Concept? + /// + /// If new concept (false) for every change to a associated description semantic we create a new semantic record + /// and directly commit it with in that moment generated stamp. + THIS_IS_A_NEW_CONCEPT, + + THIS_CONCEPT_ENTITY_FACADE, + /// On window creation we got a uuid from our parent identifying our window. Only related to this window instance + THIS_UNIQUE_CONCEPT_TOPIC, + + ASOCIATED_FQN_DESCRIPTION_SEMANTICS, + ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS, + + /// Either point to ourselves, to other fqn semantics or otherName (regular Name) semantics. + /// + /// If this is null we know that we need to create a new semantic from scratch in nameForm + SELECTED_DESCRIPTION_SEMANTIC, + + // stuff from god + VIEW_PROPERTIES, + /// Each journal window has a unique topic. E.g a uuid identifying our journal parent + ASOCIATED_JOURNAL_WINDOW_TOPIC, + + SELECTED_PROPERTY_WINDOW_KIND, + PROPERTY_WINDOW_OPEN, + + UNCOMMITED_CHANGES, + + HAS_VALID_STAMP, + + CURRENT_STAMP_FORM, + + AXIOM, + + } + + // --- Property ValuesTypes --- + + /// The current PaneType in Property View + public enum SelectedPropertyWindowKind{ + STAMP, + MENU, + NAME_MENU, + NAME_FORM, + HISTORY, + HIERARCHY, + COMMENTS, + NONE + } + + public sealed interface SelectedDescriptionSemantic + permits SemanticPublicId, UncommittedSemanticNameDescr {} + + public record SemanticPublicId(PublicId value) implements SelectedDescriptionSemantic {} + public record UncommittedSemanticNameDescr(DescrName value) implements SelectedDescriptionSemantic {} - // -------------------------------------------- - // Known properties - // -------------------------------------------- - public static String CURRENT_ENTITY = "entityFacade"; - public static String FULLY_QUALIFIED_NAMES = "fullyQualifiedNames"; - public static String CONCEPT_STAMP_VIEW_MODEL = "stampViewModel"; - public static String OTHER_NAMES = "otherNames"; - public static String AXIOM = "axiom"; - // Axiom values public static String SUFFICIENT_SET = "Sufficient Set"; public static String NECESSARY_SET = "Necessary Set"; + public ConceptViewModelNext() { + addProperty(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT, true) + .addProperty(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, (EntityFacade) null) + .addProperty(ConceptPropertyKeys.THIS_UNIQUE_CONCEPT_TOPIC, (UUID) null) + .addProperty(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS, new ArrayList()) + .addProperty(ConceptPropertyKeys.ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS, new ArrayList()) + .addProperty(ConceptPropertyKeys.SELECTED_DESCRIPTION_SEMANTIC, (SelectedDescriptionSemantic) null) + .addProperty(ConceptPropertyKeys.VIEW_PROPERTIES, (ViewProperties) null) + .addProperty(ConceptPropertyKeys.ASOCIATED_JOURNAL_WINDOW_TOPIC, (UUID) null) + .addProperty(ConceptPropertyKeys.SELECTED_PROPERTY_WINDOW_KIND, (SelectedPropertyWindowKind) null) + .addProperty(ConceptPropertyKeys.PROPERTY_WINDOW_OPEN, false) + .addProperty(ConceptPropertyKeys.UNCOMMITED_CHANGES, false) + .addProperty(ConceptPropertyKeys.HAS_VALID_STAMP, false) + .addProperty(ConceptPropertyKeys.CURRENT_STAMP_FORM, (StampFormViewModelBase) null) + .addProperty(ConceptPropertyKeys.AXIOM, (String) null) + ; - public ConceptViewModel() { - super(); // addProperty(MODE, VIEW); By default - addProperty(CURRENT_ENTITY, (EntityFacade) null) - .addProperty(FULLY_QUALIFIED_NAMES, (Collection) new ArrayList<>()) - .addProperty(OTHER_NAMES, (Collection) new ArrayList<>()) - .addProperty(CONCEPT_STAMP_VIEW_MODEL, (ViewModel) null) - .addProperty(AXIOM, (String) null); + } - //FIXME add a STAMP validator + public ViewProperties getViewProperties() { + return getPropertyValue(ConceptPropertyKeys.VIEW_PROPERTIES); + } + + public void updateModel() { + // TODO: entity facade && newConcept? + + // + // identicon effected by, VIEW_PROPERTIES, THIS_CONCEPT_ENTITY_FACADE + // stamp effected by, THIS_IS_A_NEW_CONCEPT HAS_VALID_STAMP THIS_CONCEPT_ENTITY_FACADE + + // + // addButton effected by, HAS_VALID_STAMP + // TODO: fqn displayed and otherName should be reactive to entityFacade changes + // fqn displayed effected by, ASOCIATED_FQN_CONCEPTS, HAS_VALID_STAMP + // otherName displayed effected by, ASOCIATED_OTHER_NAME_CONCEPTS, HAS_VALID_STAMP + + // - // In Create Mode the fqn is required. - addValidator(FULLY_QUALIFIED_NAMES, "Fully Qualified Names",(ObservableList observableList, ViewModel _ ) -> { - if (observableList.isEmpty()){ - return new ValidationMessage(FULLY_QUALIFIED_NAMES, MessageType.ERROR, "${%s} is required".formatted(FULLY_QUALIFIED_NAMES)); - } - return VALID; - }); - // Axiom should be selected - addValidator(AXIOM, "Axiom",(ReadOnlyStringProperty prop, ViewModel _ ) -> { - if (prop.isNull().get() - || (prop.get() instanceof String axiom - && !(SUFFICIENT_SET.equals(axiom) || NECESSARY_SET.equals(axiom)))) { - return new ValidationMessage(AXIOM, MessageType.ERROR, "${%s} is required and must be a %s or %s. Axiom = %s".formatted(AXIOM, SUFFICIENT_SET, NECESSARY_SET, prop.get())); - } - return VALID; - }); } /** * Validates the view model and if there are no errors, save to the database. - * Is called everytime user is adding data to ConceptViewModel. * * @return */ @@ -121,9 +157,10 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { save(); // View Model xfer values. does not save to the database but validates data and then copies data from properties to model values. // Validation errors will not create record. - if (!getValidationMessages().isEmpty()) { - return false; - } + // TODO: add new validator +// if (!getValidationMessages().isEmpty()) { +// return false; +// } // stamp is populated? if (!(Boolean)stampFormViewModel.getPropertyValue(IS_CONFIRMED_OR_SUBMITTED)) { @@ -131,7 +168,7 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { } // Create concept - List fqnList = getObservableList(FULLY_QUALIFIED_NAMES); + List fqnList = getObservableList(ConceptPropertyKeys.ASOCIATED_FQN_DESCRIPTION_SEMANTICS); // TODO: this still assumes that on creation we can only have a FQN DescrName fqnDescrName = fqnList.get(0); Transaction transaction = Transaction.make("New concept for: " + fqnDescrName.getNameText()); @@ -165,7 +202,7 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { AxiomBuilderRecord ab = newConceptBuilder.axiomBuilder(); // determine sufficient or necessary - if (NECESSARY_SET.equals(getValue(AXIOM))) { + if (NECESSARY_SET.equals(getValue(ConceptPropertyKeys.AXIOM))) { ab.withNecessarySet( // ab.makeConceptReference(TinkarTerm.LANGUAGE), // ab.makeConceptReference(TinkarTerm.DESCRIPTION_ASSEMBLAGE), @@ -173,7 +210,7 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { ab.makeSome(TinkarTerm.PART_OF, TinkarTerm.ANONYMOUS_CONCEPT) /*ab.makeSome(TinkarTerm.PART_OF, TinkarTerm.LANGUAGE)*/) ); - } else if (SUFFICIENT_SET.equals(getValue(AXIOM))) { + } else if (SUFFICIENT_SET.equals(getValue(ConceptPropertyKeys.AXIOM))) { ab.withSufficientSet( // ab.makeConceptReference(TinkarTerm.LANGUAGE), // ab.makeConceptReference(TinkarTerm.DESCRIPTION_ASSEMBLAGE), @@ -185,7 +222,8 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { // add the axiom buildAxiom(ab, conceptRecord, stampEntity, transaction); - List otherNames = (List) getValueMap().get(OTHER_NAMES); + // TODO: clean up this type mess ... + List otherNames = (List) getValueMap().get(ConceptPropertyKeys.ASOCIATED_OTHER_NAME_DESCRIPTION_SEMANTICS); if (otherNames.size() > 0) { // if there are other names defined, then add them to the newly created concept saveOtherNameWithinCreateConcept(transaction, stampEntity, otherNames, conceptFacade); @@ -207,44 +245,20 @@ public boolean createConcept(StampFormViewModelBase stampFormViewModel) { // alert the user of the concept being created and were it exists JournalController.toast() - .show( - Toast.Status.SUCCESS, - String.format("Concept created %s, %s, %s", pathText, moduleText, statusText) - ); + .show( + Toast.Status.SUCCESS, + String.format("Concept created %s, %s, %s", pathText, moduleText, statusText) + ); // place inside as current Concept - setValue(CURRENT_ENTITY, conceptFacade); - setPropertyValue(CURRENT_ENTITY, conceptFacade); - setValue(MODE, EDIT); - setPropertyValue(MODE, EDIT); + // TODO: ;( + setValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, conceptFacade); + setPropertyValue(ConceptPropertyKeys.THIS_CONCEPT_ENTITY_FACADE, conceptFacade); + setValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT, false); + setPropertyValue(ConceptPropertyKeys.THIS_IS_A_NEW_CONCEPT, false); return true; } - private void buildAxiom(AxiomBuilderRecord axiomBuilder, ConceptRecord conceptRecord, StampEntity stampEntity, Transaction transaction) { - DiTreeEntity.Builder axiomTreeEntityBuilder = DiTreeEntity.builder(); - EntityVertex rootVertex = EntityVertex.make(axiomBuilder); - axiomTreeEntityBuilder.setRoot(rootVertex); - recursiveAddChildren(axiomTreeEntityBuilder, rootVertex, axiomBuilder); - - ImmutableList axiomField = Lists.immutable.of(axiomTreeEntityBuilder.build()); - SemanticRecord statedAxioms = SemanticRecord.build(UUID.randomUUID(), - TinkarTerm.EL_PLUS_PLUS_STATED_AXIOMS_PATTERN.nid(), - conceptRecord.nid(), - stampEntity.lastVersion(), - axiomField); - transaction.addComponent(statedAxioms); - Entity.provider().putEntity(statedAxioms); - } - - private void recursiveAddChildren(DiTreeEntity.Builder axiomTreeBuilder, EntityVertex parentVertex, AxiomBuilderRecord parentAxiom) { - for (AxiomBuilderRecord child : parentAxiom.children()) { - EntityVertex childVertex = EntityVertex.make(child); - axiomTreeBuilder.addVertex(childVertex); - axiomTreeBuilder.addEdge(childVertex, parentVertex); - recursiveAddChildren(axiomTreeBuilder, childVertex, child); - } - } - private void saveFQNwithinCreateConcept(Transaction transaction, StampEntity stampEntity, DescrName fqnNameDescr, ConceptFacade conceptFacade) { // create a new public id for the FQN semantic @@ -329,68 +343,30 @@ private void saveOtherNameWithinCreateConcept(Transaction transaction, StampEnti }); } - public void addOtherName(EditCoordinateRecord editCoordinateRecord, DescrName otherName) { - - Transaction transaction = Transaction.make(); - - StampEntity stampEntity = transaction.getStamp( - State.fromConcept(otherName.getStatus()), // active, inactive, etc - System.currentTimeMillis(), - getViewProperties().nodeView().editCoordinate().getAuthorForChanges().nid(), - otherName.getModule().nid(), // SNOMED CT, LOINC, etc - TinkarTerm.DEVELOPMENT_PATH.nid()); // Should this be defaulted??? - - // get the public id of the referenced concept - PublicId conceptRecordPublicId = otherName.getParentConcept(); - - int conceptNid = EntityService.get().nidForPublicId(conceptRecordPublicId); - - // the versions that we will first populate with the existing versions of the semantic - RecordListBuilder versions = RecordListBuilder.make(); - - // the new semantic will need a new public id - PublicId newOtherNamePublicId = PublicIds.newRandom(); - - SemanticRecord descriptionSemantic = SemanticRecord.makeNew(newOtherNamePublicId, TinkarTerm.DESCRIPTION_PATTERN.nid(), - conceptNid, versions); - - // we are grabbing the form data - // populating the field values for the new version we are writing - MutableList descriptionFields = Lists.mutable.empty(); - descriptionFields.add(otherName.getLanguage()); - descriptionFields.add(otherName.getNameText()); - descriptionFields.add(otherName.getCaseSignificance()); - descriptionFields.add(TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE); - - // iterating over the existing versions and adding them to a new record list builder - descriptionSemantic.versions().forEach(version -> versions.add(version)); - - // adding the new (edit form) version here - versions.add(SemanticVersionRecordBuilder.builder() - .chronology(descriptionSemantic) - .stampNid(stampEntity.nid()) - .fieldValues(descriptionFields.toImmutable()) - .build()); - - // apply the updated versions to the new semantic record - SemanticRecord newSemanticRecord = SemanticRecordBuilder.builder(descriptionSemantic).versions(versions.toImmutable()).build(); - - otherName.setSemanticPublicId(newSemanticRecord.publicId()); - // put the new semantic record in the transaction - transaction.addComponent(newSemanticRecord); - - // perform the save - Entity.provider().putEntity(newSemanticRecord); - - // commit the transaction - CommitTransactionTask commitTransactionTask = new CommitTransactionTask(transaction); - TinkExecutor.threadPool().submit(commitTransactionTask); + private void buildAxiom(AxiomBuilderRecord axiomBuilder, ConceptRecord conceptRecord, StampEntity stampEntity, Transaction transaction) { + DiTreeEntity.Builder axiomTreeEntityBuilder = DiTreeEntity.builder(); + EntityVertex rootVertex = EntityVertex.make(axiomBuilder); + axiomTreeEntityBuilder.setRoot(rootVertex); + recursiveAddChildren(axiomTreeEntityBuilder, rootVertex, axiomBuilder); - LOG.info("transaction complete"); + ImmutableList axiomField = Lists.immutable.of(axiomTreeEntityBuilder.build()); + SemanticRecord statedAxioms = SemanticRecord.build(UUID.randomUUID(), + TinkarTerm.EL_PLUS_PLUS_STATED_AXIOMS_PATTERN.nid(), + conceptRecord.nid(), + stampEntity.lastVersion(), + axiomField); + transaction.addComponent(statedAxioms); + Entity.provider().putEntity(statedAxioms); } - public ViewProperties getViewProperties() { - return getPropertyValue(VIEW_PROPERTIES); + private void recursiveAddChildren(DiTreeEntity.Builder axiomTreeBuilder, EntityVertex parentVertex, AxiomBuilderRecord parentAxiom) { + for (AxiomBuilderRecord child : parentAxiom.children()) { + EntityVertex childVertex = EntityVertex.make(child); + axiomTreeBuilder.addVertex(childVertex); + axiomTreeBuilder.addEdge(childVertex, parentVertex); + recursiveAddChildren(axiomTreeBuilder, childVertex, child); + } } -} \ No newline at end of file + +} diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModel.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModel.java index cba1e63f0e..b8fb861f3e 100644 --- a/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModel.java +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModel.java @@ -31,6 +31,7 @@ import dev.ikm.tinkar.entity.StampEntity; import dev.ikm.tinkar.entity.transaction.CommitTransactionTask; import dev.ikm.tinkar.entity.transaction.Transaction; +import dev.ikm.tinkar.terms.EntityProxy; import dev.ikm.tinkar.terms.State; import dev.ikm.tinkar.terms.TinkarTerm; import javafx.beans.property.ReadOnlyObjectProperty; @@ -124,7 +125,7 @@ public Set findAllCaseSignificants(ViewProperties viewProperties) return CASE_SIGNIFICANCE_OPTIONS; } - public void updateFullyQualifiedName(PublicId publicId, ViewProperties viewProperties) { + private void updateSemanticName(PublicId publicId, ViewProperties viewProperties, EntityProxy.Concept semanticType) { Transaction transaction = Transaction.make(); StampEntity stampEntity = transaction.getStamp( @@ -151,7 +152,7 @@ public void updateFullyQualifiedName(PublicId publicId, ViewProperties viewPrope descriptionFields.add(getValue(LANGUAGE)); descriptionFields.add(getValue(NAME_TEXT)); descriptionFields.add(getValue(CASE_SIGNIFICANCE)); - descriptionFields.add(TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE); + descriptionFields.add(semanticType); // iterating over the existing versions and adding them to a new record list builder theSemantic.versions().forEach(version -> versions.add(version)); @@ -177,6 +178,20 @@ public void updateFullyQualifiedName(PublicId publicId, ViewProperties viewPrope TinkExecutor.threadPool().submit(commitTransactionTask); } + public void updateFullyQualifiedName(PublicId publicId, ViewProperties viewProperties) { + EntityProxy.Concept semanticType = TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE; + + updateSemanticName(publicId, viewProperties , semanticType); + LOG.info("transaction complete"); + } + + public void updateOtherName(PublicId publicId, ViewProperties viewProperties) { + EntityProxy.Concept semanticType = TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE; + + updateSemanticName(publicId, viewProperties , semanticType); + LOG.info("transaction complete"); + } + public DescrName create() { return new DescrName(getValue(PARENT_PUBLIC_ID), getValue(NAME_TEXT), @@ -200,56 +215,5 @@ public void updateData(DescrName editDescrName) { editDescrName.setSemanticPublicId(getValue(SEMANTIC_PUBLIC_ID)); } - public void updateOtherName(PublicId publicId, ViewProperties viewProperties) { - Transaction transaction = Transaction.make(); - StampEntity stampEntity = transaction.getStamp( - State.fromConcept(getValue(STATUS)), // active, inactive, etc - System.currentTimeMillis(), - viewProperties.nodeView().editCoordinate().getAuthorForChanges().nid(), - ((ConceptEntity)getValue(MODULE)).nid(), // SNOMED CT, LOINC, etc - TinkarTerm.DEVELOPMENT_PATH.nid()); //TODO should this path come from the parent concept's path? - - // existing semantic - SemanticEntity theSemantic = EntityService.get().getEntityFast(publicId.asUuidList()); - - - // the versions that we will first populate with the existing versions of the semantic - RecordListBuilder versions = RecordListBuilder.make(); - - SemanticRecord descriptionSemantic = SemanticRecord.makeNew(publicId, TinkarTerm.DESCRIPTION_PATTERN.nid(), - theSemantic.referencedComponentNid(), versions); - - // we grabbing the form data - // populating the field values for the new version we are writing - MutableList descriptionFields = Lists.mutable.empty(); - descriptionFields.add(getValue(LANGUAGE)); - descriptionFields.add(getValue(NAME_TEXT)); - descriptionFields.add(getValue(CASE_SIGNIFICANCE)); - descriptionFields.add(TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE); - - // iterating over the existing versions and adding them to a new record list builder - theSemantic.versions().forEach(version -> versions.add(version)); - - // adding the new (edit form) version here - versions.add(SemanticVersionRecordBuilder.builder() - .chronology(descriptionSemantic) - .stampNid(stampEntity.nid()) - .fieldValues(descriptionFields.toImmutable()) - .build()); - // apply the updated versions to the new semantic record - SemanticRecord newSemanticRecord = SemanticRecordBuilder.builder(descriptionSemantic).versions(versions.toImmutable()).build(); - - // put the new semantic record in the transaction - transaction.addComponent(newSemanticRecord); - - // perform the save - Entity.provider().putEntity(newSemanticRecord); - - // commit the transaction - CommitTransactionTask commitTransactionTask = new CommitTransactionTask(transaction); - TinkExecutor.threadPool().submit(commitTransactionTask); - - LOG.info("transaction complete"); - } } diff --git a/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModelNext.java b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModelNext.java new file mode 100644 index 0000000000..79fa3f4a07 --- /dev/null +++ b/kview/src/main/java/dev/ikm/komet/kview/mvvm/viewmodel/DescrNameViewModelNext.java @@ -0,0 +1,249 @@ +package dev.ikm.komet.kview.mvvm.viewmodel; + +import dev.ikm.komet.framework.view.ViewProperties; +import dev.ikm.komet.kview.mvvm.model.DescrName; +import dev.ikm.tinkar.common.id.PublicId; +import dev.ikm.tinkar.common.service.PublicIdService; +import dev.ikm.tinkar.common.service.TinkExecutor; +import dev.ikm.tinkar.coordinate.stamp.calculator.Latest; +import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator; +import dev.ikm.tinkar.entity.*; +import dev.ikm.tinkar.entity.transaction.CommitTransactionTask; +import dev.ikm.tinkar.entity.transaction.Transaction; +import dev.ikm.tinkar.terms.*; +import org.carlfx.cognitive.viewmodel.ValidationViewModel; + +import dev.ikm.tinkar.terms.ComponentWithNid; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Set; + +import static dev.ikm.komet.kview.mvvm.model.DataModelHelper.fetchDescendentsOfConcept; +import static dev.ikm.tinkar.terms.TinkarTerm.*; + + +public class DescrNameViewModelNext extends ValidationViewModel { + private static final Logger LOG = LoggerFactory.getLogger(DescrNameViewModelNext.class); + + public enum DescrPropKeys { + /// displayable Name + NAME, + + SELECTED_NAME_TYPE, + /// all possible associated name types + NAME_TYPE_VARIANTS, // ( FQN or otherName ? ) + + SELECTED_CASE_SIGNIFICANCE, + /// all possible associated case types + CASE_SIGNIFICANCE_VARIANTS, + + SELECTED_STATUS, + /// all possible associated statuses + STATUS_VARIANTS, + + SELECTED_MODULE, + /// all possible associated modules + MODULE_VARIANTS, + + SELECTED_LANGUAGE, + /// all possible associated languages + LANGUAGE_VARIANTS, + + // TODO: check if the following are needed in this model + /// the public ID of the description semantic that this class represents + SEMANTIC_PUBLIC_ID, + /// the public ID of the parent concept of this description semantic + PARENT_CONCEPT_ID, + + // TODO: this are old ones used before + // used to display the title of the add/edit screen? + TITLE_TEXT, + + VIEW_PROPERTIES, + } + + public DescrNameViewModelNext (ViewProperties viewProperties) { + + + addProperty(DescrPropKeys.NAME, (String) null) + .addProperty(DescrPropKeys.SELECTED_NAME_TYPE, (ComponentWithNid) null) + .addProperty(DescrPropKeys.NAME_TYPE_VARIANTS, Collections.emptyList(), true) + + .addProperty(DescrPropKeys.SELECTED_CASE_SIGNIFICANCE, (ComponentWithNid) null) + .addProperty(DescrPropKeys.CASE_SIGNIFICANCE_VARIANTS, Collections.emptyList(), true) + + .addProperty(DescrPropKeys.SELECTED_STATUS, (ComponentWithNid) null) + .addProperty(DescrPropKeys.STATUS_VARIANTS, Collections.emptyList(), true) + + .addProperty(DescrPropKeys.SELECTED_MODULE, (ComponentWithNid) null) + .addProperty(DescrPropKeys.MODULE_VARIANTS, Collections.emptyList(), true) + + .addProperty(DescrPropKeys.SELECTED_LANGUAGE, (ComponentWithNid) null) + .addProperty(DescrPropKeys.LANGUAGE_VARIANTS, Collections.emptyList(), true) + + .addProperty(DescrPropKeys.VIEW_PROPERTIES, (ViewProperties) viewProperties) + .addProperty(DescrPropKeys.TITLE_TEXT, (String) "hello world"); + + // This works only for a DescNameViewModel that works ontop of a concept + fetchSemanticFieldChoicesViaParentConcept(viewProperties); + + // run validators when the following properties change. + doOnChange(this::validate, + DescrPropKeys.NAME, + DescrPropKeys.SELECTED_NAME_TYPE, + DescrPropKeys.SELECTED_CASE_SIGNIFICANCE, + DescrPropKeys.SELECTED_STATUS, + DescrPropKeys.SELECTED_MODULE, + DescrPropKeys.SELECTED_LANGUAGE + ); + + + + } + + /// Copy View values into the Model + @Override + public DescrNameViewModelNext save() { + LOG.info("Copy: View State --> Model state"); + super.save(); + + return this; + } + + /// Copy Model values into the View + @Override + public DescrNameViewModelNext reset() { + LOG.info("Copy: View State <-- Model state"); + super.reset(); + + return this; + } + + + private void fetchSemanticFieldChoicesViaParentConcept(ViewProperties viewProperties) { + Set nameTypes = fetchDescendentsOfConcept(viewProperties, TinkarTerm.DESCRIPTION_TYPE.publicId()); + Set caseSignificances = fetchDescendentsOfConcept(viewProperties, DESCRIPTION_CASE_SIGNIFICANCE.publicId()); + Set states = fetchDescendentsOfConcept(viewProperties, TinkarTerm.STATUS_VALUE.publicId()); + Set languages = fetchDescendentsOfConcept(viewProperties, TinkarTerm.LANGUAGE.publicId()); + Set modules = fetchDescendentsOfConcept(viewProperties, TinkarTerm.MODULE.publicId()); + + setPropertyValues(DescrPropKeys.NAME_TYPE_VARIANTS, nameTypes); + setPropertyValues(DescrPropKeys.CASE_SIGNIFICANCE_VARIANTS, caseSignificances); + setPropertyValues(DescrPropKeys.STATUS_VARIANTS, states); + setPropertyValues(DescrPropKeys.LANGUAGE_VARIANTS, languages); + setPropertyValues(DescrPropKeys.MODULE_VARIANTS, modules); + } + + + /// Create a new semantic that points to a Concept derived from the provided ViewProperties + /// + /// Notice: should only be used on ViewProperties that actually include a "parent" Concept + public void createNewSemantic(ViewProperties viewProperties) { + fetchSemanticFieldChoicesViaParentConcept(viewProperties); + + setPropertyValue(DescrPropKeys.NAME, (String) null); + setPropertyValue(DescrPropKeys.SELECTED_NAME_TYPE, (ComponentWithNid) null); + setPropertyValue(DescrPropKeys.SELECTED_CASE_SIGNIFICANCE, (ComponentWithNid) null); + setPropertyValue(DescrPropKeys.SELECTED_STATUS, (ComponentWithNid) null); + setPropertyValue(DescrPropKeys.SELECTED_MODULE, (ComponentWithNid) null); + setPropertyValue(DescrPropKeys.SELECTED_LANGUAGE, (ComponentWithNid) null); + } + + /// Update a semantic + /// + /// Useful when creating a new Concept and the Concept was not commited + /// + /// @param descrName provides the semantic that wants to be updated + public void updateNonCommitedSemantic(DescrName descrName, ViewProperties viewProperties) { + fetchSemanticFieldChoicesViaParentConcept(viewProperties); + + setPropertyValue(DescrPropKeys.NAME, (String) descrName.getNameText()); + setPropertyValue(DescrPropKeys.SELECTED_NAME_TYPE, (ComponentWithNid) descrName.getNameType()); + setPropertyValue(DescrPropKeys.SELECTED_CASE_SIGNIFICANCE, (ComponentWithNid) descrName.getCaseSignificance()); + setPropertyValue(DescrPropKeys.SELECTED_STATUS, (ComponentWithNid) descrName.getStatus()); + setPropertyValue(DescrPropKeys.SELECTED_MODULE, (ComponentWithNid) descrName.getModule()); + setPropertyValue(DescrPropKeys.SELECTED_LANGUAGE, (ComponentWithNid) descrName.getLanguage()); + } + + + public void updateExistingSemantic(PublicId semanticNameId, ViewProperties viewProperties) { + int semanticNid = EntityService.get().nidForPublicId(semanticNameId); + Latest semanticEntityVersionLatest = viewProperties.calculator().latest(semanticNid); + SemanticEntityVersion bla = semanticEntityVersionLatest.get(); + LOG.info("SemanticEntityVersion we got on updatingExistingSemantic call"); + LOG.info(bla.toString()); + } + + + public void updateFullyQualifiedName(PublicId publicId, ViewProperties viewProperties) { + EntityProxy.Concept semanticType = TinkarTerm.FULLY_QUALIFIED_NAME_DESCRIPTION_TYPE; + + updateSemanticName(publicId, viewProperties , semanticType); + LOG.info("transaction complete"); + } + + public void updateOtherName(PublicId publicId, ViewProperties viewProperties) { + EntityProxy.Concept semanticType = TinkarTerm.REGULAR_NAME_DESCRIPTION_TYPE; + + updateSemanticName(publicId, viewProperties , semanticType); + LOG.info("transaction complete"); + } + + private void updateSemanticName(PublicId publicId, ViewProperties viewProperties, EntityProxy.Concept semanticType) { + Transaction transaction = Transaction.make(); + + StampEntity stampEntity = transaction.getStamp( + State.fromConcept(getValue(DescrPropKeys.SELECTED_STATUS)), // active, inactive, etc + System.currentTimeMillis(), + viewProperties.nodeView().editCoordinate().getAuthorForChanges().nid(), + ((ConceptEntity)getValue(DescrPropKeys.SELECTED_MODULE)).nid(), // SNOMED CT, LOINC, etc + TinkarTerm.DEVELOPMENT_PATH.nid()); //TODO should this path come from the parent concept's path? + + + // existing semantic + SemanticEntity theSemantic = EntityService.get().getEntityFast(publicId.asUuidList()); + + + // the versions that we will first populate with the existing versions of the semantic + RecordListBuilder versions = RecordListBuilder.make(); + + SemanticRecord descriptionSemantic = SemanticRecord.makeNew(publicId, TinkarTerm.DESCRIPTION_PATTERN.nid(), + theSemantic.referencedComponentNid(), versions); + + // we are grabbing the form data + // populating the field values for the new version we are writing + MutableList descriptionFields = Lists.mutable.empty(); + descriptionFields.add(getValue(DescrPropKeys.SELECTED_LANGUAGE)); + descriptionFields.add(getValue(DescrPropKeys.NAME)); + descriptionFields.add(getValue(DescrPropKeys.SELECTED_CASE_SIGNIFICANCE)); + descriptionFields.add(semanticType); + + // iterating over the existing versions and adding them to a new record list builder + theSemantic.versions().forEach(version -> versions.add(version)); + + // adding the new (edit form) version here + versions.add(SemanticVersionRecordBuilder.builder() + .chronology(descriptionSemantic) + .stampNid(stampEntity.nid()) + .fieldValues(descriptionFields.toImmutable()) + .build()); + + // apply the updated versions to the new semantic record + SemanticRecord newSemanticRecord = SemanticRecordBuilder.builder(descriptionSemantic).versions(versions.toImmutable()).build(); + + // put the new semantic record in the transaction + transaction.addComponent(newSemanticRecord); + + // perform the save + Entity.provider().putEntity(newSemanticRecord); + + // commit the transaction + CommitTransactionTask commitTransactionTask = new CommitTransactionTask(transaction); + TinkExecutor.threadPool().submit(commitTransactionTask); + } + +} diff --git a/kview/src/main/java/module-info.java b/kview/src/main/java/module-info.java index 1604ef4873..f7c9afee95 100644 --- a/kview/src/main/java/module-info.java +++ b/kview/src/main/java/module-info.java @@ -42,7 +42,9 @@ requires javafx.controls; requires org.slf4j; requires javafx.base; - + requires dev.ikm.tinkar.entity; + requires dev.ikm.tinkar.terms; + requires dev.ikm.tinkar.common; exports dev.ikm.komet.kview.state; exports dev.ikm.komet.kview.state.pattern; diff --git a/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-details.fxml b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-details.fxml index 727dd53bbe..d2613bd5b3 100644 --- a/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-details.fxml +++ b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-details.fxml @@ -3,399 +3,487 @@ - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + - - - - - - - - - - -
- -
-
- - - - + + - - - -
- -
-
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+ +
+
+ + + +
+ + + +
+
+ +
- -
-
-
-
- - - - +
+
+
+
+
+ + + +
diff --git a/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-prop-menu.fxml b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-prop-menu.fxml new file mode 100644 index 0000000000..e4299c2e12 --- /dev/null +++ b/kview/src/main/resources/dev/ikm/komet/kview/mvvm/view/concept/concept-prop-menu.fxml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + +