From b1155dfcd2b02891c5158a0ce2b1d1871a86ab11 Mon Sep 17 00:00:00 2001 From: Carsten Wickner Date: Tue, 26 Sep 2017 23:48:49 +0200 Subject: [PATCH] implement combined analysis view (#16, #17) * introduce view toggles for parts of the analysis * introduce single AnalysisPanel instead of the completely separate two views * fix bug in specific scenario with splitProposition --- .gitignore | 1 + .../components/AbstractAisProjectView.java | 2 +- .../swing/components/ProjectOverView.java | 2 +- .../hmx/scitos/hmx/core/ModelHandlerImpl.java | 73 +- .../hmx/scitos/hmx/core/i18n/HmxMessage.java | 24 +- .../hmx/core/option/HmxGeneralOption.java | 8 +- .../hmx/scitos/hmx/core/i18n/HmxMessage.xml | 16 +- .../scitos/hmx/core/i18n/HmxMessage_de.xml | 16 +- .../scitos/hmx/core/ModelHandlerImplTest.java | 45 + .../scitos/hmx/view/ContextMenuFactory.java | 115 ++- .../hmx/scitos/hmx/view/IPericopeView.java | 14 +- .../components/AbstractAnalysisPanel.java | 97 --- .../view/swing/components/AnalysisPanel.java | 773 ++++++++++++++++++ .../components/AnalysisViewSettings.java | 181 ++++ .../components/CombinedAnalysesPanel.java | 407 --------- .../components/IAnalysisViewSettings.java | 144 ++++ .../swing/components/SemAnalysisPanel.java | 538 ------------ .../hmx/view/swing/components/SemControl.java | 155 ---- .../swing/components/SingleProjectView.java | 316 +++++-- .../swing/components/SynAnalysisPanel.java | 245 ------ .../hmx/view/swing/components/SynControl.java | 168 ---- .../swing/elements/AbstractProposition.java | 562 ------------- .../view/swing/elements/ArrowStackLabel.java | 91 +++ .../hmx/view/swing/elements/IConnectable.java | 8 - .../view/swing/elements/SemProposition.java | 163 ---- .../view/swing/elements/SynProposition.java | 261 ------ .../{SynItem.java => ViewClauseItem.java} | 90 +- .../view/swing/elements/ViewProposition.java | 749 +++++++++++++++++ .../{SemRelation.java => ViewRelation.java} | 104 ++- ...xtender.java => ViewRelationExtender.java} | 10 +- .../swing/option/HmxGeneralOptionPanel.java | 8 - .../swing/option/HmxLanguageOptionPanel.java | 8 +- .../hmx/view/swing/HmxViewProjectTest.java | 89 +- .../hmx/scitos/view/ContextMenuBuilder.java | 47 +- .../java/org/hmx/scitos/view/ScitosIcon.java | 12 +- .../org/hmx/scitos/view/swing/MainView.java | 2 +- .../hmx/scitos/view/swing/ScitosClient.java | 14 +- .../view/swing/util/table/TreeTable.java | 66 +- .../src/main/resources/icons/fatcow/grid.png | Bin 0 -> 178 bytes .../main/resources/icons/fatcow/node_tree.png | Bin 0 -> 601 bytes .../resources/icons/misc/relations_red.png | Bin 0 -> 2813 bytes 41 files changed, 2604 insertions(+), 3020 deletions(-) delete mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AbstractAnalysisPanel.java create mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisPanel.java create mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisViewSettings.java delete mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/CombinedAnalysesPanel.java create mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/IAnalysisViewSettings.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemAnalysisPanel.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemControl.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynAnalysisPanel.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynControl.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/AbstractProposition.java create mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ArrowStackLabel.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemProposition.java delete mode 100755 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynProposition.java rename scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/{SynItem.java => ViewClauseItem.java} (85%) create mode 100644 scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewProposition.java rename scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/{SemRelation.java => ViewRelation.java} (82%) rename scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/{SemRelationExtender.java => ViewRelationExtender.java} (82%) create mode 100644 scitos.view/src/main/resources/icons/fatcow/grid.png create mode 100644 scitos.view/src/main/resources/icons/fatcow/node_tree.png create mode 100644 scitos.view/src/main/resources/icons/misc/relations_red.png diff --git a/.gitignore b/.gitignore index 358cc65..4801179 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target/ /.project /.settings/ +**/nbactions.xml diff --git a/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/AbstractAisProjectView.java b/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/AbstractAisProjectView.java index f9c335b..4248e2e 100644 --- a/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/AbstractAisProjectView.java +++ b/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/AbstractAisProjectView.java @@ -89,7 +89,7 @@ public void actionPerformed(final ActionEvent event) { @Override public List createToolBarItems() { final List toolBarItems = new LinkedList(); - final JButton addInterviewButton = new JButton(ScitosIcon.MODEL_ELEMENT_ADD.create()); + final JButton addInterviewButton = new JButton(ScitosIcon.CLIPBOARD_ADD.create()); addInterviewButton.setToolTipText(AisMessage.INTERVIEW_NEW.get()); addInterviewButton.addActionListener(new ActionListener() { diff --git a/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/ProjectOverView.java b/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/ProjectOverView.java index 1b0af6e..b9c3b87 100644 --- a/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/ProjectOverView.java +++ b/scitos.ais/scitos.ais.view/src/main/java/org/hmx/scitos/ais/view/swing/components/ProjectOverView.java @@ -56,7 +56,7 @@ public ProjectOverView(final ScitosClient client, final AisViewProject project, super(project, project.getModelObject(), options, new BorderLayout()); this.analysisPanel = new PatternAnalysisPanel(client, project); this.add(this.analysisPanel); - final JButton addInterviewButton = new JButton(AisMessage.INTERVIEW_NEW.get(), ScitosIcon.MODEL_ELEMENT_ADD.create()); + final JButton addInterviewButton = new JButton(AisMessage.INTERVIEW_NEW.get(), ScitosIcon.CLIPBOARD_ADD.create()); addInterviewButton.addActionListener(new ActionListener() { @Override diff --git a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/ModelHandlerImpl.java b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/ModelHandlerImpl.java index b520445..bfd159c 100755 --- a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/ModelHandlerImpl.java +++ b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/ModelHandlerImpl.java @@ -567,23 +567,11 @@ public void splitProposition(final Proposition target, final ClauseItem lastItem secondPart.setLaterChildren(laterChildren); // avoid gaps in super ordinated relations - AbstractConnectable currentFocus = target; - Relation superOrdinated; - while ((superOrdinated = currentFocus.getSuperOrdinatedRelation()) != null) { - final List associates = superOrdinated.getAssociates(); - if (currentFocus != associates.get(associates.size() - 1)) { - /* - * target is not the last associate in one of its super ordinated relations; this relation will become invalid by splitting the - * targeted proposition; it needs to be removed - */ - superOrdinated.kill(); - break; - } - currentFocus = superOrdinated; - } + this.handleRelationsWhenSplittingProposition(target, secondPart); // transfer part after arrow + final Proposition partAfterArrow = target.getPartAfterArrow(); target.setPartAfterArrow(null); - secondPart.setPartAfterArrow(target.getPartAfterArrow()); + secondPart.setPartAfterArrow(partAfterArrow); // finish model changes target.getParent().insertChildPropositionAfterPrior(secondPart, target); @@ -622,6 +610,61 @@ public void splitProposition(final Proposition target, final ClauseItem lastItem this.notifyListeners(this.getModel(), false); } + /** + * When splitting a {@link Proposition} into two, super ordinated relations might no longer be valid and need to be removed to ensure model + * integrity. If the directly super ordinated {@link Relation} starts at the proposition being split, it should be moved to the new/second part. + * + * @param firstPart + * leading part of the proposition being split + * @param secondPart + * trailing part of the propostion being split + */ + private void handleRelationsWhenSplittingProposition(final Proposition firstPart, final Proposition secondPart) { + if (firstPart.getSuperOrdinatedRelation() == null) { + // nothing to handle + return; + } + AbstractConnectable currentFocus = firstPart; + Relation superOrdinated = firstPart.getSuperOrdinatedRelation(); + if (firstPart == superOrdinated.getAssociates().get(0)) { + // move relation to the new proposition in order to preserve its validity + final List newAssociates = new ArrayList(superOrdinated.getAssociates()); + newAssociates.set(0, secondPart); + superOrdinated.setAssociates(newAssociates); + final AssociateRole role = firstPart.getRole(); + firstPart.setSuperOrdinatedRelation(null, null); + secondPart.setSuperOrdinatedRelation(superOrdinated, role); + // check whether super ordinated relations are still valid after this move + currentFocus = superOrdinated; + while ((superOrdinated = currentFocus.getSuperOrdinatedRelation()) != null) { + final List associates = superOrdinated.getAssociates(); + if (currentFocus != associates.get(0)) { + /* + * moved relation is not the first associate in one of its super ordinated relations; this relation will in turn become + * invalid by splitting the targeted proposition; it needs to be removed + */ + superOrdinated.kill(); + break; + } + currentFocus = superOrdinated; + } + return; + } + do { + final List associates = superOrdinated.getAssociates(); + if (currentFocus != associates.get(associates.size() - 1)) { + /* + * target is not the last associate in one of its super ordinated relations; this relation will become invalid by + * splitting the targeted proposition; it needs to be removed + */ + superOrdinated.kill(); + break; + } + currentFocus = superOrdinated; + superOrdinated = currentFocus.getSuperOrdinatedRelation(); + } while (superOrdinated != null); + } + @Override public void resetStandaloneStateOfPartAfterArrow(final Proposition partAfterArrow) throws HmxException { final List items = partAfterArrow.getPartBeforeArrow().getItems(); diff --git a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/i18n/HmxMessage.java b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/i18n/HmxMessage.java index 0a78b7a..aa5dc29 100644 --- a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/i18n/HmxMessage.java +++ b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/i18n/HmxMessage.java @@ -58,8 +58,16 @@ public enum HmxMessage implements ILocalizableMessage { MENUBAR_PROJECT_MERGE_BEHIND("Client.MenuBar.Edit.MergeProjects.Behind"), /** menubar entry: View -> Hide/Show Proposition Labels. */ MENUBAR_TOGGLE_PROPOSITION_LABELS("Client.MenuBar.View.TogglePropositionLabels"), - /** menubar entry: View -> Hide/Show Proposition Translations. */ - MENUBAR_TOGGLE_PROPOSITION_TRANSLATIONS("Client.MenuBar.View.TogglePropositionTranslations"), + /** menubar entry: View -> Hide/Show Proposition Indentations. */ + MENUBAR_TOGGLE_PROPOSITION_INDENTATIONS("Client.MenuBar.View.TogglePropositionIndentations"), + /** menubar entry: View -> Hide/Show Relations. */ + MENUBAR_TOGGLE_RELATIONS("Client.MenuBar.View.ToggleRelations"), + /** menubar entry: View -> Hide/Show Clause Items. */ + MENUBAR_TOGGLE_CLAUSE_ITEMS("Client.MenuBar.View.ToggleClauseItems"), + /** menubar entry: View -> Hide/Show Syntactic Proposition Translations. */ + MENUBAR_TOGGLE_SYNTACTIC_TRANSLATIONS("Client.MenuBar.View.ToggleSyntacticTranslations"), + /** menubar entry: View -> Hide/Show Semantic Proposition Translations. */ + MENUBAR_TOGGLE_SEMANTIC_TRANSLATIONS("Client.MenuBar.View.ToggleSemanticTranslations"), /** in the new-project-setup: the hint label over the main text input. */ TEXTINPUT_TOPIC("TextInput.Topic"), @@ -101,9 +109,13 @@ public enum HmxMessage implements ILocalizableMessage { /** label over the comment area in the analysis mode. */ ANALYSIS_COMMENT_TOPIC("Analysis.CommentTopic"), + /** tool bar item for view preset: All Details. */ + ANALYSIS_PRESET_SHOW_ALL("Client.ToolBar.ViewPreset.AllDetails"), + /** tool bar item for view preset: Syntactical Analysis. */ + ANALYSIS_PRESET_SYNTACTICAL("Client.ToolBar.ViewPreset.SyntacticalAnalysis"), + /** tool bar item for view preset: Semantical Analysis. */ + ANALYSIS_PRESET_SEMANTICAL("Client.ToolBar.ViewPreset.SemanticalAnalysis"), - /** button to switch to the syntactical analysis view. */ - ANALYSIS_SYNTACTICAL_BUTTON("Analysis.Syntactical"), /** syntactical context menu entry: change clause item function. */ MENU_CHANGE_ITEM_FUNCTION("Analysis.Syntactical.ChangeItemFunction"), /** syntactical context menu entry: change indentation function. */ @@ -141,8 +153,6 @@ public enum HmxMessage implements ILocalizableMessage { /** syntactical context menu entry: split part-after-arrow from other part. */ MENU_RESET_PROP_PART("Analysis.Syntactical.ResetStandaloneProposition"), - /** button to switch to the syntactical analysis view. */ - ANALYSIS_SEMANTICAL_BUTTON("Analysis.Semantical"), /** semantical context menu entry: create relation. */ MENU_CREATE_RELATION("Analysis.Semantical.CreateRelation"), /** semantical context menu entry: rotate roles of relation parts. */ @@ -163,7 +173,6 @@ public enum HmxMessage implements ILocalizableMessage { /** export related labels. */ EXPORT_TITLE("Export.Title"), EXPORT_TITLE_AUTHOR("Export.Title.Author"), - EXPORT_HEIGHT("Export.Height"), EXPORT_WIDTH("Export.Width"), @@ -206,7 +215,6 @@ public enum HmxMessage implements ILocalizableMessage { PREFERENCES_GENERAL_INDENTATION("Preferences.View.IndentationWidth"), PREFERENCES_GENERAL_PROPOSITIONS("Preferences.View.Propositions"), PREFERENCES_GENERAL_PROPOSITIONS_SHOW_LABELS("Preferences.View.Propositions.ShowLabels"), - PREFERENCES_GENERAL_PROPOSITIONS_SHOW_TRANSLATIONS("Preferences.View.Propositions.ShowTranslations"), PREFERENCES_GENERAL_INPUT("Preferences.View.TextInput"), PREFERENCES_GENERAL_INPUT_SHOW_SETTINGS("Preferences.View.TextInput.ShowSettings"), PREFERENCES_GENERAL_AUTHOR("Preferences.Analysis.ProjectInfo.DefaultAuthor"), diff --git a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/option/HmxGeneralOption.java b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/option/HmxGeneralOption.java index 6c56001..9ebc0f4 100644 --- a/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/option/HmxGeneralOption.java +++ b/scitos.hmx/scitos.hmx.core/src/main/java/org/hmx/scitos/hmx/core/option/HmxGeneralOption.java @@ -37,8 +37,6 @@ public enum HmxGeneralOption implements IOptionSetting { COMMENTED_BORDER_COLOR("Commented.BorderColor", ConversionUtil.toString(Color.GREEN)), /** user setting: whether the labels on the analysis views should be visible by default. */ SHOW_PROPOSITION_LABELS("Analysis.Proposition.ShowLabels", String.valueOf(true)), - /** user setting: whether the translations on the analysis views should be visible by default. */ - SHOW_PROPOSITION_TRANSLATIONS("Analysis.Proposition.ShowTranslations", String.valueOf(true)), /** user setting: width of syntactical indentations. */ INDENTATION_WIDTH("SynAnalysis.IndentationWidth", "50"), /** user setting: whether the setting area in the new-project-setup should be visible by default. */ @@ -57,10 +55,8 @@ public enum HmxGeneralOption implements IOptionSetting { /** * Constructor. * - * @param attributeKey - * actual settings key - * @param defaultValue - * default value to return if no value was specified before + * @param attributeKey actual settings key + * @param defaultValue default value to return if no value was specified before */ private HmxGeneralOption(final String attributeKey, final String defaultValue) { this.key = attributeKey; diff --git a/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage.xml b/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage.xml index 6662f99..040de74 100644 --- a/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage.xml +++ b/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage.xml @@ -1,8 +1,8 @@ - Insert the Comment for the lowered Element here - Go To Semantical Alter relation type Create Relation with checked Elements Hide all Roles @@ -29,7 +28,6 @@ Display Roles in this Column Remove Relation Switch Roles - Go To Syntactical Change Clause Item Function Change Indentation Function Highlight Clause Item @@ -59,8 +57,15 @@ Continue? are being removed from this project. Continue? Edit Project Info + Hide/Show Clause Items + Hide/Show Proposition Indentations Hide/Show Proposition Labels - Hide/Show Proposition Translations + Hide/Show Relations + Hide/Show Semantic Translations + Hide/Show Syntactic Translations + View: All Details + View: Semantical Analysis + View: Syntactical Analysis At least one other element needs to be checked. The chosen relation cannot be created with more then two associates. @@ -198,7 +203,6 @@ It is being displayed as entry in the Syntactical Analysis' context menus.Indentation Width On Propositions in Analysis View Show labels - Show translations On Text Input View for new Analysis Show settings Author diff --git a/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage_de.xml b/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage_de.xml index a4d61e4..ce4a223 100644 --- a/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage_de.xml +++ b/scitos.hmx/scitos.hmx.core/src/main/resources/org/hmx/scitos/hmx/core/i18n/HmxMessage_de.xml @@ -1,8 +1,8 @@ - Geben Sie hier den Kommentar für das eingedrückte Element ein - Wechsel auf Semantische Ändere Beziehungsart Setze ausgewählte Elemente in Beziehung Alle Rollen ausblenden @@ -29,7 +28,6 @@ Rollen dieser Ebene einblenden Entferne Beziehung Wechsle Rollen aus - Wechsel auf Syntaktische Ändere Satzgliedfunktion Ändere Einrückungsfunktion Hebe Satzglied hervor @@ -57,8 +55,15 @@ Wollen Sie wirklich fortfahren? Ausgewählte Propositionen Entfernen Soll(en) die ausgewählte(n) Proposition(en) wirklich gelöscht werden? Projektinformationen + Satzglieder: Aus-/Einblenden + Propositionseinrückungen: Aus-/Einblenden Propositionsbezeichner: Aus-/Einblenden - Propositionsübersetzungen: Aus-/Einblenden + Beziehungen: Aus-/Einblenden + Semantische Übersetzungen: Aus-/Einblenden + Syntaktische Übersetzungen: Aus-/Einblenden + Ansicht: Alles + Ansicht: Semantische Analyse + Ansicht: Syntaktische Analyse Es müssen mindestens zwei Elemente (über ihre CheckBoxen) ausgewählt sein. Die gewählte Beziehung kann @@ -198,7 +203,6 @@ Er wird in the Syntaktischen Analyse im entsprechenden Auswahlmenü angezeigt.Breite der Einrückungen Auf Propositionen in Analyse-Ansicht Kurzbezeichnerfelder einblenden - Übersetzungsfelder einblenden Beim Start der Texteingabe Einstellungen einblenden Autor diff --git a/scitos.hmx/scitos.hmx.core/src/test/java/org/hmx/scitos/hmx/core/ModelHandlerImplTest.java b/scitos.hmx/scitos.hmx.core/src/test/java/org/hmx/scitos/hmx/core/ModelHandlerImplTest.java index 2bbe894..9b9af5f 100644 --- a/scitos.hmx/scitos.hmx.core/src/test/java/org/hmx/scitos/hmx/core/ModelHandlerImplTest.java +++ b/scitos.hmx/scitos.hmx.core/src/test/java/org/hmx/scitos/hmx/core/ModelHandlerImplTest.java @@ -1308,6 +1308,51 @@ public void testSplitProposition_6() throws HmxException { Assert.assertNull(propositionThird.getSuperOrdinatedRelation()); } + /** + * Test: of {@code splitProposition(Proposition, ClauseItem)} after the first item of the first part of a {@link Proposition} with two enclosed + * children. + * + * @throws HmxException + * impossible to split {@link Proposition} part after first of two items + */ + @Test + public void testSplitProposition_7() throws HmxException { + final Proposition propositionFirst = this.pericope.getPropositionAt(0); + final Proposition propositionSecond = this.pericope.getPropositionAt(1); + final Proposition propositionThird = this.pericope.getPropositionAt(2); + final Proposition propositionFourth = this.pericope.getPropositionAt(3); + final Proposition propositionFifth = this.pericope.getPropositionAt(4); + this.modelHandler.mergePropositions(propositionFirst, propositionFourth); + this.modelHandler.createRelation(Arrays.asList(propositionFirst, propositionSecond), ModelHandlerImplTest.defaultRelationTemplate); + final Relation survivingLeadRelation = propositionSecond.getSuperOrdinatedRelation(); + this.modelHandler.createRelation(Arrays.asList(propositionThird, propositionFifth), ModelHandlerImplTest.defaultRelationTemplate); + final Relation survivingTrailRelation = propositionThird.getSuperOrdinatedRelation(); + this.modelHandler.createRelation(Arrays.asList(survivingLeadRelation, survivingTrailRelation), ModelHandlerImplTest.defaultRelationTemplate); + final Relation rootRelation = survivingLeadRelation.getSuperOrdinatedRelation(); + final ClauseItem itemFirst = propositionFirst.getItems().get(0); + final ClauseItem itemSecond = propositionFirst.getItems().get(1); + this.modelHandler.splitProposition(propositionFirst, itemFirst); + final List newPropositions = this.pericope.getFlatText(); + Assert.assertEquals(6, newPropositions.size()); + Assert.assertEquals(Collections.singletonList(itemFirst), newPropositions.get(0).getItems()); + Assert.assertEquals(Collections.singletonList(itemSecond), newPropositions.get(1).getItems()); + Assert.assertSame(propositionSecond, newPropositions.get(2)); + Assert.assertSame(propositionThird, newPropositions.get(3)); + Assert.assertSame(propositionFourth, newPropositions.get(4)); + Assert.assertSame(propositionFifth, newPropositions.get(5)); + Assert.assertNull(newPropositions.get(0).getPartAfterArrow()); + Assert.assertSame(propositionFourth, newPropositions.get(1).getPartAfterArrow()); + Assert.assertSame(newPropositions.get(1), propositionFourth.getPartBeforeArrow()); + Assert.assertNull(newPropositions.get(0).getSuperOrdinatedRelation()); + Assert.assertSame(survivingLeadRelation, newPropositions.get(1).getSuperOrdinatedRelation()); + Assert.assertSame(survivingLeadRelation, propositionSecond.getSuperOrdinatedRelation()); + Assert.assertSame(survivingTrailRelation, propositionThird.getSuperOrdinatedRelation()); + Assert.assertSame(survivingTrailRelation, propositionFifth.getSuperOrdinatedRelation()); + Assert.assertNotNull(rootRelation); + Assert.assertSame(rootRelation, survivingLeadRelation.getSuperOrdinatedRelation()); + Assert.assertSame(rootRelation, survivingTrailRelation.getSuperOrdinatedRelation()); + } + /** * Test: of {@code resetStandaloneStateOfPartAfterArrow(Proposition)} for two top level {@link Proposition}s with a single enclosed child. * diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/ContextMenuFactory.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/ContextMenuFactory.java index 056910c..2a91bc4 100755 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/ContextMenuFactory.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/ContextMenuFactory.java @@ -71,12 +71,12 @@ private ContextMenuFactory() { * designated popup owner * @return created popup */ - public static ContextMenuBuilder createSynItemPopup(final IPericopeView viewReference, final ClauseItem selectedItem) { + public static ContextMenuBuilder createClauseItemPopup(final IPericopeView viewReference, final ClauseItem selectedItem) { final ContextMenuBuilder created = new ContextMenuBuilder(); ContextMenuFactory.addFunctionChangeEntry(created, viewReference, HmxMessage.MENU_CHANGE_ITEM_FUNCTION, selectedItem, false); created.addSeparator(); - ContextMenuFactory.addSynItemEntries(created, viewReference, selectedItem); - ContextMenuFactory.addSynPropositionEntries(created, viewReference, selectedItem.getParent()); + ContextMenuFactory.addClauseItemEntries(created, viewReference, selectedItem); + ContextMenuFactory.addPropositionEntries(created, viewReference, selectedItem.getParent()); return created; } @@ -90,11 +90,11 @@ public static ContextMenuBuilder createSynItemPopup(final IPericopeView viewRefe * designated popup owner * @return created popup */ - public static ContextMenuBuilder createSynItemAfterArrowPopup(final IPericopeView viewReference, final ClauseItem selectedItem) { + public static ContextMenuBuilder createClauseItemAfterArrowPopup(final IPericopeView viewReference, final ClauseItem selectedItem) { final ContextMenuBuilder created = new ContextMenuBuilder(); ContextMenuFactory.addFunctionChangeEntry(created, viewReference, HmxMessage.MENU_CHANGE_ITEM_FUNCTION, selectedItem, false); created.addSeparator(); - ContextMenuFactory.addSynItemEntries(created, viewReference, selectedItem); + ContextMenuFactory.addClauseItemEntries(created, viewReference, selectedItem); created.addSeparator(); ContextMenuFactory.addResetStandalonePropositionEntry(created, viewReference, selectedItem.getParent()); return created; @@ -109,9 +109,9 @@ public static ContextMenuBuilder createSynItemAfterArrowPopup(final IPericopeVie * designated popup owner * @return created popup */ - public static ContextMenuBuilder createSynPropositionPopup(final IPericopeView viewReference, final Proposition selectedProposition) { + public static ContextMenuBuilder createPropositionPopup(final IPericopeView viewReference, final Proposition selectedProposition) { final ContextMenuBuilder created = new ContextMenuBuilder(); - ContextMenuFactory.addSynPropositionEntries(created, viewReference, selectedProposition); + ContextMenuFactory.addPropositionEntries(created, viewReference, selectedProposition); return created; } @@ -124,27 +124,12 @@ public static ContextMenuBuilder createSynPropositionPopup(final IPericopeView v * designated popup owner * @return created popup */ - public static ContextMenuBuilder createSynPropositionAfterArrowPopup(final IPericopeView viewReference, final Proposition selectedProposition) { + public static ContextMenuBuilder createPropositionAfterArrowPopup(final IPericopeView viewReference, final Proposition selectedProposition) { final ContextMenuBuilder created = new ContextMenuBuilder(); ContextMenuFactory.addResetStandalonePropositionEntry(created, viewReference, selectedProposition); return created; } - /** - * Create a {@link ContextMenuBuilder} with only one entry to create a {@link Relation} over the clicked {@link Proposition}. - * - * @param viewReference - * the view the request for this context menu originated from - * @param selectedConnectable - * designated popup owner - * @return created popup - */ - public static ContextMenuBuilder createSemPropositionPopup(final IPericopeView viewReference, final AbstractConnectable selectedConnectable) { - final ContextMenuBuilder created = new ContextMenuBuilder(); - ContextMenuFactory.addCreateOrAlterRelationEntry(created, viewReference, selectedConnectable, false); - return created; - } - /** * Create a {@link ContextMenuBuilder} with four entries to create a {@link Relation} over the clicked {@link Relation}, rotate its roles, change * its type or to delete it. @@ -155,9 +140,11 @@ public static ContextMenuBuilder createSemPropositionPopup(final IPericopeView v * designated popup owner * @return created popup */ - public static ContextMenuBuilder createSemRelationPopup(final IPericopeView viewReference, final Relation selectedRelation) { + public static ContextMenuBuilder createRelationPopup(final IPericopeView viewReference, final Relation selectedRelation) { final ContextMenuBuilder created = new ContextMenuBuilder(); - ContextMenuFactory.addCreateOrAlterRelationEntry(created, viewReference, selectedRelation, false); + if (selectedRelation.getSuperOrdinatedRelation() == null) { + ContextMenuFactory.addCreateOrAlterRelationEntry(created, viewReference, selectedRelation, false); + } created.addItem(HmxMessage.MENU_ROTATE_RELATION_ROLES.get(), new CMenuItemAction() { @Override @@ -266,7 +253,7 @@ public void processSelectEvent() throws HmxException { * @param item * {@link ClauseItem} to be changed */ - private static void addSynItemEntries(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, final ClauseItem item) { + private static void addClauseItemEntries(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, final ClauseItem item) { final List itemList = item.getParent().getItems(); final int itemIndex = CollectionUtil.indexOfInstance(itemList, item); // merge specified clause item with its prior clause item @@ -318,7 +305,7 @@ public void processSelectEvent() throws HmxException { partBuffer.append(' '); } } - ContextMenuFactory.addHighlightSynItemEntry(popupMenu, viewReference, item); + ContextMenuFactory.addHighlightClauseItemEntry(popupMenu, viewReference, item); popupMenu.addSeparator(); if (isNotLastItemInParent) { @@ -344,7 +331,7 @@ public void processSelectEvent() throws HmxException { * @param item * {@link ClauseItem} to be highlighted */ - private static void addHighlightSynItemEntry(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, final ClauseItem item) { + private static void addHighlightClauseItemEntry(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, final ClauseItem item) { final CMenu highlightEntry = popupMenu.addMenu(HmxMessage.MENU_HIGHLIGHT_ITEM.get()); // set PLAIN final Map styles = new LinkedHashMap(); @@ -376,32 +363,40 @@ public void processSelectEvent() throws HmxException { * @param proposition * view represenation of the {@link Proposition} to be changed */ - private static void addSynPropositionEntries(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, + private static void addPropositionEntries(final ContextMenuBuilder popupMenu, final IPericopeView viewReference, final Proposition proposition) { - // merge propositions - popupMenu.addItem(HmxMessage.MENU_MERGE_CHECKED_PROP.get(), new CMenuItemAction() { - - @Override - public void processSelectEvent() throws HmxException { - viewReference.submitChangesToModel(); - ContextMenuFactory.mergeSynPropositions(viewReference, proposition); - } - }); - // indent proposition under parent - ContextMenuFactory.addFunctionChangeEntry(popupMenu, viewReference, HmxMessage.MENU_INDENT_PROP, proposition, true); - // change function of indented proposition - if (proposition.getParent() instanceof Proposition) { - popupMenu.addSeparator(); - ContextMenuFactory.addFunctionChangeEntry(popupMenu, viewReference, HmxMessage.MENU_CHANGE_PROP_FUNCTION, proposition, false); - // remove an indentation - popupMenu.addItem(HmxMessage.MENU_UNINDENT_PROP.get(), new CMenuItemAction() { + if (viewReference.getViewSettings().isShowingPropositionIndentations()) { + // merge propositions + popupMenu.addItem(HmxMessage.MENU_MERGE_CHECKED_PROP.get(), new CMenuItemAction() { @Override public void processSelectEvent() throws HmxException { viewReference.submitChangesToModel(); - ContextMenuFactory.removeOneIndentation(viewReference, proposition); + ContextMenuFactory.mergePropositions(viewReference, proposition); } }); + // indent proposition under parent + ContextMenuFactory.addFunctionChangeEntry(popupMenu, viewReference, HmxMessage.MENU_INDENT_PROP, proposition, true); + // change function of indented proposition + if (proposition.getParent() instanceof Proposition) { + popupMenu.addSeparator(); + ContextMenuFactory.addFunctionChangeEntry(popupMenu, viewReference, HmxMessage.MENU_CHANGE_PROP_FUNCTION, proposition, false); + // remove an indentation + popupMenu.addItem(HmxMessage.MENU_UNINDENT_PROP.get(), new CMenuItemAction() { + + @Override + public void processSelectEvent() throws HmxException { + viewReference.submitChangesToModel(); + ContextMenuFactory.removeOneIndentation(viewReference, proposition); + } + }); + } + } + if (viewReference.getViewSettings().isShowingRelations() && proposition.getSuperOrdinatedRelation() == null) { + if (!popupMenu.isEmpty()) { + popupMenu.addSeparator(); + } + ContextMenuFactory.addCreateOrAlterRelationEntry(popupMenu, viewReference, proposition, false); } } @@ -417,14 +412,16 @@ public void processSelectEvent() throws HmxException { */ private static void addResetStandalonePropositionEntry(final ContextMenuBuilder popup, final IPericopeView viewReference, final Proposition proposition) { - popup.addItem(HmxMessage.MENU_RESET_PROP_PART.get(), new CMenuItemAction() { + if (viewReference.getViewSettings().isShowingPropositionIndentations()) { + popup.addItem(HmxMessage.MENU_RESET_PROP_PART.get(), new CMenuItemAction() { - @Override - public void processSelectEvent() throws HmxException { - viewReference.submitChangesToModel(); - viewReference.getModelHandler().resetStandaloneStateOfPartAfterArrow(proposition); - } - }); + @Override + public void processSelectEvent() throws HmxException { + viewReference.submitChangesToModel(); + viewReference.getModelHandler().resetStandaloneStateOfPartAfterArrow(proposition); + } + }); + } } /** @@ -437,7 +434,7 @@ public void processSelectEvent() throws HmxException { * @throws HmxException * invalid user input */ - static void mergeSynPropositions(final IPericopeView viewReference, final Proposition selectedProposition) throws HmxException { + static void mergePropositions(final IPericopeView viewReference, final Proposition selectedProposition) throws HmxException { // get all checked propositions on the syntactical analysis panel final List checked = viewReference.getSelectedPropositions(selectedProposition); final int size = checked.size(); @@ -524,7 +521,7 @@ static void removeOneIndentation(final IPericopeView viewReference, final Propos /** * Add a submenu to the given {@link ContextMenuBuilder} for creating a {@link Relation} over the selected associates including the given one or * for altering the type of given {@link Relation}. - * + * * @param popup * the context menu to add the created submenu to * @param viewReference @@ -585,7 +582,7 @@ public void processSelectEvent() throws HmxException { /** * Build the text representing the given {@link RelationTemplate}. - * + * * @param template * the {@link RelationTemplate} to represent as text * @return the representing text @@ -598,7 +595,7 @@ public static String buildRelationLabel(final RelationTemplate template) { /** * Build the text representing the {@link Relation} consisting of the given roles. - * + * * @param roles * the associate roles the represented {@link Relation} is comprised of * @param onlyAlterType @@ -638,7 +635,7 @@ private static String buildRelationLabel(final List roles, final if (index == null) { index = 1; } else { - index = index + 1; + index++; } itemLabel.append(index); indices.put(singleRole, index); diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/IPericopeView.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/IPericopeView.java index fbfc42f..4843093 100644 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/IPericopeView.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/IPericopeView.java @@ -25,6 +25,7 @@ import org.hmx.scitos.hmx.domain.ISemanticalRelationProvider; import org.hmx.scitos.hmx.domain.model.AbstractConnectable; import org.hmx.scitos.hmx.domain.model.Proposition; +import org.hmx.scitos.hmx.view.swing.components.IAnalysisViewSettings; import org.hmx.scitos.hmx.view.swing.elements.AbstractCommentable; import org.hmx.scitos.view.swing.IUndoManagedView; @@ -39,18 +40,11 @@ public interface IPericopeView extends ISemanticalRelationProvider, IUndoManaged HmxModelHandler getModelHandler(); /** - * Getter for the view preference whether the label fields of propositions should be displayed or not. + * Getter for the view preferences what parts should be displayed. * - * @return whether to displayed proposition label fields + * @return view settings to apply */ - boolean isShowingPropositionLabels(); - - /** - * Getter for the view preference whether the translation fields of propositions should be displayed or not. - * - * @return whether to displayed proposition translation fields - */ - boolean isShowingPropositionTranslations(); + IAnalysisViewSettings getViewSettings(); /** * Collect the list of selected {@link Proposition}s in the syntactical analysis, if it is currently active (i.e. displayed). diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AbstractAnalysisPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AbstractAnalysisPanel.java deleted file mode 100644 index c2d7b4d..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AbstractAnalysisPanel.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.awt.LayoutManager; - -import javax.swing.JPanel; - -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.hmx.domain.model.Pericope; -import org.hmx.scitos.hmx.view.IPericopeView; - -/** Abstract base panel for a single analysis. */ -abstract class AbstractAnalysisPanel extends JPanel { - - /** The view this panel is displayed in. */ - private final IPericopeView viewReference; - - /** - * Constructor: initializing the invisible and empty panel with the given layout manager. - * - * @param viewReference - * the view this panel is displayed in - * @param layout - * the main layout manager to apply - */ - protected AbstractAnalysisPanel(final IPericopeView viewReference, final LayoutManager layout) { - super(layout); - this.setVisible(false); - this.viewReference = viewReference; - } - - /** - * Getter for the view project instance this belongs to. - * - * @return associated view project - */ - public IPericopeView getViewReference() { - return this.viewReference; - } - - /** - * Add the {@link #getModelChangeListener() ModelChangeListener} to the associated project and display the current state of the {@link Pericope}. - * - * @see #repaintPericope() - */ - public void activate() { - this.setVisible(true); - this.getViewReference().getModelHandler().addModelChangeListener(this.getModelChangeListener()); - this.repaintPericope(); - } - - /** - * Remove the {@link #getModelChangeListener() ModelChangeListener} from the associated project and make this panel invisible. - */ - public void deactivate() { - this.submitChangesToModel(); - this.setVisible(false); - this.getViewReference().getModelHandler().removeModelChangeListener(this.getModelChangeListener()); - } - - /** - * Fully rebuild the displayed representation of the current {@link Pericope}. - */ - public abstract void repaintPericope(); - - /** - * Ensure that any pending changes have been submitted to the model handler for proper processing. - */ - public abstract void submitChangesToModel(); - - /** - * Getter for the {@link ModelChangeListener} handling updates of this panel. - * - * @return the associated model listener - * @see #activate() - * @see #deactivate() - */ - protected abstract ModelChangeListener getModelChangeListener(); -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisPanel.java new file mode 100644 index 0000000..b7ac348 --- /dev/null +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisPanel.java @@ -0,0 +1,773 @@ +/* + Copyright (C) 2017 HermeneutiX.org + + This file is part of SciToS. + + SciToS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SciToS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SciToS. If not, see . + */ + +package org.hmx.scitos.hmx.view.swing.components; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import org.hmx.scitos.core.UndoManager; + +import org.hmx.scitos.domain.ModelChangeListener; +import org.hmx.scitos.domain.ModelEvent; +import org.hmx.scitos.domain.util.CollectionUtil; +import org.hmx.scitos.domain.util.ComparisonUtil; +import org.hmx.scitos.hmx.core.HmxModelHandler; +import org.hmx.scitos.hmx.core.i18n.HmxMessage; +import org.hmx.scitos.hmx.domain.ICommentable; +import org.hmx.scitos.hmx.domain.ISemanticalRelationProvider; +import org.hmx.scitos.hmx.domain.model.AbstractConnectable; +import org.hmx.scitos.hmx.domain.model.ClauseItem; +import org.hmx.scitos.hmx.domain.model.Pericope; +import org.hmx.scitos.hmx.domain.model.Proposition; +import org.hmx.scitos.hmx.domain.model.Relation; +import org.hmx.scitos.hmx.domain.model.RelationTemplate; +import org.hmx.scitos.hmx.view.IPericopeView; +import org.hmx.scitos.hmx.view.swing.elements.AbstractCommentable; +import org.hmx.scitos.hmx.view.swing.elements.IConnectable; +import org.hmx.scitos.hmx.view.swing.elements.ViewRelation; +import org.hmx.scitos.hmx.view.swing.elements.ViewProposition; +import org.hmx.scitos.hmx.view.swing.elements.ViewRelationExtender; +import org.hmx.scitos.view.swing.components.ScaledLabel; +import org.hmx.scitos.view.swing.components.ScaledTextPane; + +/** + * Panel displaying the whole pericope for the actual analysis. + */ +public final class AnalysisPanel extends JPanel implements IPericopeView, ModelChangeListener { + + /** The represented project's model handler instance. */ + private final HmxModelHandler modelHandler; + /** + * The provider of available semantical {@link RelationTemplate}s, to be offered via the elements' context menus. + */ + private final ISemanticalRelationProvider relationProvider; + /** The undo manager for the whole model. */ + private final UndoManager undoManager; + /** Flag indicating that an un-do or re-do operation is currently in progress. */ + private boolean undoInProgress = false; + + /** + * The current maximum depth of the represented tree of {@link Relation}s. + */ + private int levels = 0; + /** The single main component allowing everything to be scrolled. */ + final JScrollPane scrollPane; + /** The actual container for view elements. */ + private final JPanel contentArea = new JPanel(new GridBagLayout()); + /** + * The header bar allowing to expand/collapse {@link Relation} columns by toggling the roles' visibility. + */ + final JPanel contentHeaders = new JPanel(new GridBagLayout()) { + + @Override + public void updateUI() { + if (AnalysisPanel.this.contentHeaders != null) { + // reset to apply potentially changed scale factor + AnalysisPanel.this.resetHeaders(); + } + } + }; + /** + * Additional panel ensuring the trailing alignment of the propositions while relations are shown. + */ + private final JPanel leftContentSpacing = new JPanel(null); + /** + * Additional panel ensuring the leading alignment of the propositions while relations are hidden. + */ + private final JPanel rightContentSpacing = new JPanel(null); + /** + * The input area at the bottom of the view, allowing the display and modification of a selected element's comment. + */ + private final JTextPane commentArea; + + /** + * View settings indicating what parts of the analysis should be displayed or not. + */ + private final IAnalysisViewSettings viewSettings; + /** + * The indices of currently collapsed {@link Relation} columns, i.e. where the associate roles are currently hidden to reduce required horizontal + * space. + */ + private final Set foldedLevels = new HashSet(); + /** + * Complete list of currently contained view components representing the {@link Pericope}'s {@link Proposition}s. + */ + private List propositionList; + /** + * Complete mapping of {@link Relation}s to their representing view components. + */ + private Map relationMap; + /** + * The most recently selected commentable model element currently associated with the {@link #commentArea}. + */ + private AbstractCommentable lastSelectedCommentable; + + /** + * Constructor. + * + * @param modelHandler the represented project's model handler instance + * @param relationProvider the provider of available semantical {@link RelationTemplate}s, to be offered via the elements' context menus + * @param viewSettings user settings determining what parts to show + */ + protected AnalysisPanel(final HmxModelHandler modelHandler, final ISemanticalRelationProvider relationProvider, + final IAnalysisViewSettings viewSettings) { + super(new GridLayout(0, 1)); + this.modelHandler = modelHandler; + this.relationProvider = relationProvider; + this.viewSettings = viewSettings; + this.undoManager = new UndoManager(modelHandler.getModel()); + + this.scrollPane = this.initScrollableContent(); + // initialize the commentArea to be reachable by commentable components + this.commentArea = new ScaledTextPane(); + + final JSplitPane splitArea = new JSplitPane(JSplitPane.VERTICAL_SPLIT, this.scrollPane, this.initCommentPanel()); + splitArea.setBorder(null); + splitArea.setResizeWeight(1); + this.add(splitArea); + this.setBorder(null); + + this.refresh(); + this.addAncestorListener(new AncestorListener() { + @Override + public void ancestorAdded(final AncestorEvent event) { + // ensure logging of model change events by the UndoManager + modelHandler.addModelChangeListener(AnalysisPanel.this); + // reset size of comment area on every tab change; TODO handle this more elegantly in the future + splitArea.setDividerLocation(-1); + } + + @Override + public void ancestorRemoved(final AncestorEvent event) { + /* + * unregister UndoManager as long as nothing is shown (nothing can be changed); this is to avoid multiple of these listeners if the + * respective tabs are being closed and re-opened repeatedly + */ + modelHandler.removeModelChangeListener(AnalysisPanel.this); + } + + @Override + public void ancestorMoved(final AncestorEvent event) { + // we don't care about any movement + } + }); + } + + /** + * Initialize the whole layout. + * + * @return the created scroll pane + */ + private JScrollPane initScrollableContent() { + // make the whole analysis view scrollable + final JPanel background = new JPanel(new GridBagLayout()); + // initialize content area + final GridBagConstraints mainConstraints = new GridBagConstraints(); + mainConstraints.anchor = GridBagConstraints.FIRST_LINE_END; + mainConstraints.fill = GridBagConstraints.BOTH; + mainConstraints.gridx = 1; + mainConstraints.gridy = 0; + background.add(this.contentArea, mainConstraints); + // make sure it is always at the top + final GridBagConstraints bottomSpace = new GridBagConstraints(); + bottomSpace.weighty = 1; + bottomSpace.gridx = 1; + bottomSpace.gridy = 1; + background.add(new JPanel(null), bottomSpace); + final GridBagConstraints rightSpace = new GridBagConstraints(); + rightSpace.weightx = 1; + rightSpace.gridx = 2; + rightSpace.gridy = 0; + background.add(this.rightContentSpacing, rightSpace); + // wrap the headers to get equal behavior + final JPanel headerView = new JPanel(new GridBagLayout()); + // make sure it is always on the right + final GridBagConstraints leftSpace = new GridBagConstraints(); + leftSpace.weightx = 1; + leftSpace.gridx = 0; + leftSpace.gridy = 0; + background.add(this.leftContentSpacing, leftSpace); + headerView.add(new JPanel(null), leftSpace); + headerView.add(this.contentHeaders, mainConstraints); + headerView.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK)); + final ComponentOrientation orientation; + if (this.getModelHandler().getModel().isLeftToRightOriented()) { + orientation = ComponentOrientation.LEFT_TO_RIGHT; + } else { + orientation = ComponentOrientation.RIGHT_TO_LEFT; + } + background.setComponentOrientation(orientation); + this.contentArea.setComponentOrientation(orientation); + headerView.setComponentOrientation(orientation); + this.contentHeaders.setComponentOrientation(orientation); + + final JScrollPane scrollablePane = new JScrollPane(background); + scrollablePane.setBorder(null); + scrollablePane.setColumnHeaderView(headerView); + scrollablePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + return scrollablePane; + } + + /** + * Initialize the comment area at the bottom. + * + * @return panel containing the scrollable comment text area + */ + private JPanel initCommentPanel() { + // add the comment area for both views + final JPanel commentPanel = new JPanel(new GridBagLayout()); + commentPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 10, 5)); + final JLabel topicLabel = new ScaledLabel(HmxMessage.ANALYSIS_COMMENT_TOPIC.get()); + topicLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5)); + commentPanel.add(topicLabel); + this.commentArea.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5)); + final JScrollPane scrollableComment = new JScrollPane(this.commentArea); + scrollableComment.setBorder(BorderFactory.createLoweredBevelBorder()); + scrollableComment.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + final GridBagConstraints doubleSpan = new GridBagConstraints(); + doubleSpan.fill = GridBagConstraints.BOTH; + doubleSpan.weightx = 1; + doubleSpan.weighty = 1; + doubleSpan.gridx = 0; + doubleSpan.gridy = 1; + commentPanel.add(scrollableComment, doubleSpan); + commentPanel.setPreferredSize(new Dimension(1, 80)); + return commentPanel; + } + + @Override + public HmxModelHandler getModelHandler() { + return this.modelHandler; + } + + @Override + public IAnalysisViewSettings getViewSettings() { + return this.viewSettings; + } + + @Override + public void modelChanged(final ModelEvent event) { + // ignore change event thrown by the own undo/redo action + if (!this.undoInProgress) { + this.undoManager.undoableEditHappened(this.getModelHandler().getModel()); + } + // deal with different kinds of targets and event types + final Object target = event.getTarget(); + SwingUtilities.invokeLater(new Thread("HmX View Model Update") { + + @Override + public void run() { + if (target instanceof ClauseItem) { + final ViewProposition targetParent = AnalysisPanel.this.getRepresentative(((ClauseItem) target).getParent()); + if (targetParent != null) { + targetParent.refreshClauseItem((ClauseItem) target); + return; + } + } else if (target instanceof Proposition && AnalysisPanel.this.getRepresentative((Proposition) target).refresh()) { + return; + } + AnalysisPanel.this.refresh(); + } + }); + } + + /** + * Fully rebuild the displayed representation of the current {@link Pericope}. + */ + @Override + public void refresh() { + // remember vertical position + final int verticalPosition = this.scrollPane.getVerticalScrollBar().getValue(); + // clear view + this.submitChangesToModel(); + this.setVisible(false); + final boolean showingRelations = this.viewSettings.isShowingRelations(); + this.leftContentSpacing.setVisible(showingRelations); + this.rightContentSpacing.setVisible(!showingRelations); + this.contentArea.removeAll(); + // get the currently used origin text font + this.propositionList = new ArrayList(); + // fill the propositionList + int propositionIndexOffset = 0; + for (final Proposition singleTopLevelProposition : this.getModelHandler().getModel().getText()) { + propositionIndexOffset = this.addViewPropositionToList(singleTopLevelProposition, propositionIndexOffset, 0); + } + // show pericope + this.levels = this.calculateLevels(); + this.displayPropositions(); + this.relationMap = new HashMap(); + if (this.viewSettings.isShowingRelations()) { + this.displayRelations(); + } + this.resetHeaders(); + // reset vertical position + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + AnalysisPanel.this.setVisible(true); + AnalysisPanel.this.scrollPane.getVerticalScrollBar().setValue(verticalPosition); + } + }); + } + + /** + * Transfer the {@link ViewProposition}s contained in the {@link #propositionList} to the displayed view. + */ + private void displayPropositions() { + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = Math.max(1, this.levels); + constraints.gridy = 0; + for (final ViewProposition singleProposition : this.propositionList) { + this.contentArea.add(singleProposition, constraints); + constraints.gridy++; + } + } + + /** + * Build the {@link #relationMap} and display it; assuming the already created {@link #propositionList}. + */ + private void displayRelations() { + ViewProposition singleProposition = this.propositionList.get(0); + while (singleProposition != null) { + Relation singleRelation = singleProposition.getRepresented().getSuperOrdinatedRelation(); + final Proposition follower; + if (singleRelation == null) { + follower = singleProposition.getRepresented().getFollowingConnectableProposition(); + } else { + // get the highest relation over the singleProposition + while (singleRelation.getSuperOrdinatedRelation() != null) { + singleRelation = singleRelation.getSuperOrdinatedRelation(); + } + // add highest and all of its subordinated relations in map + this.insertRelationTree(singleRelation); + follower = singleRelation.getLastPropositionContained().getFollowingConnectableProposition(); + } + if (follower == null) { + break; + } + singleProposition = this.getRepresentative(follower); + } + } + + /** + * Display the specified {@link Relation} and all of its subordinated {@link AbstractConnectable}s. + * + * @param relation + * {@link Relation} to display + */ + private void insertRelationTree(final Relation relation) { + // insert all subordinated relations first + for (final AbstractConnectable singleAssociate : relation) { + if (singleAssociate instanceof Relation) { + this.insertRelationTree((Relation) singleAssociate); + } + } + final ViewRelation viewRepresentative = new ViewRelation(this, relation, this.foldedLevels); + // insert the relation itself in the map + this.relationMap.put(relation, viewRepresentative); + // build constraints + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridheight = (int) (viewRepresentative.getLastGridY() - viewRepresentative.getFirstGridY() + 1); + constraints.gridx = this.levels - viewRepresentative.getDepth(); + constraints.gridy = (int) (viewRepresentative.getFirstGridY() - 0.5); + // display + this.contentArea.add(viewRepresentative, constraints); + viewRepresentative.setVisible(false); + viewRepresentative.setVisible(true); + // extend lines if there is a gap between relation and its associates + for (final AbstractConnectable singleAssociate : relation) { + int depth = viewRepresentative.getDepth() - 1; + final IConnectable associateRepresentative = this.getRepresentative(singleAssociate); + final double connectY = associateRepresentative.getConnectY(); + if ((connectY % 1) == 0) { + constraints.gridheight = 2; + } else { + constraints.gridheight = 1; + } + constraints.gridy = (int) (connectY - 0.5); + while (depth > associateRepresentative.getDepth()) { + constraints.gridx = this.levels - depth; + this.contentArea.add(new ViewRelationExtender(), constraints); + depth--; + } + } + } + + /** + * Calculate the maximum number of super ordinated {@link Relation}s. + * + * @return calculated maximum level + */ + private int calculateLevels() { + int max = 0; + for (final ViewProposition singleProposition : this.propositionList) { + Relation singleSuperordinated = singleProposition.getRepresented().getSuperOrdinatedRelation(); + int depth; + for (depth = 0; singleSuperordinated != null; depth++) { + singleSuperordinated = singleSuperordinated.getSuperOrdinatedRelation(); + } + max = Math.max(max, depth); + } + return (max + 1); + } + + /** + * Add the specified {@link Proposition} to the list of {@link ViewProposition}s WITHOUT adding it to the view. + * + * @param proposition {@link Proposition} to add to list + * @param offset next free proposition index + * @param level level of nested indentation of the given proposition towards the top-level propositions (which are on level 0) + * @return new {@code offset}, i.e. the highest now occupied proposition index + 1 + */ + private int addViewPropositionToList(final Proposition proposition, final int offset, final int level) { + // first: add all prior children + final List priorChildren = proposition.getPriorChildren(); + int propositionOffset = offset; + if (priorChildren != null) { + for (final Proposition singlePriorChild : priorChildren) { + propositionOffset = this.addViewPropositionToList(singlePriorChild, propositionOffset, level + 1); + } + } + // second: add the proposition itself + final Proposition partBeforeArrow = proposition.getPartBeforeArrow(); + final ViewProposition viewProposition; + if (partBeforeArrow == null) { + viewProposition = ViewProposition.createSynPropositionByLevel(this, proposition, propositionOffset, level); + } else { + final ViewProposition viewPartBeforeArrow = this.getRepresentative(partBeforeArrow); + viewProposition = ViewProposition.createSynPropositionByPartBeforeArrow(this, proposition, propositionOffset, viewPartBeforeArrow); + // show arrows + final int beforeArrowPos = CollectionUtil.indexOfInstance(this.propositionList, viewPartBeforeArrow); + final List propositionsAfterPriorPart = this.propositionList.subList(beforeArrowPos + 1, this.propositionList.size()); + // count number of arrows to set + int arrowCount = 0; + // ignore partAfterArrows + for (final ViewProposition enclosedProposition : propositionsAfterPriorPart) { + if (enclosedProposition == viewProposition) { + break; + } + if (enclosedProposition.getRepresented().getPartBeforeArrow() == null) { + arrowCount++; + } + } + // show arrows in part before arrow and target + viewPartBeforeArrow.setRightArrowCount(arrowCount); + viewProposition.setLeftArrowCount(arrowCount); + } + propositionOffset++; + this.propositionList.add(viewProposition); + // third: add all later children + final List laterChildren = proposition.getLaterChildren(); + if (laterChildren != null) { + for (final Proposition singleLaterChild : laterChildren) { + propositionOffset = this.addViewPropositionToList(singleLaterChild, propositionOffset, level + 1); + } + } + // finally: add the part after arrow + final Proposition partAfterArrow = proposition.getPartAfterArrow(); + if (partAfterArrow != null) { + propositionOffset = this.addViewPropositionToList(partAfterArrow, propositionOffset, level); + } + return propositionOffset; + } + + @Override + public void submitChangesToModel() { + // the propositions might have pending changes (e.g. the label and translation fields) + if (this.propositionList != null) { + for (final ViewProposition singleProposition : this.propositionList) { + singleProposition.submitChangesToModel(); + } + } + // also take care of any newly entered comment specifically + this.handleSelectedCommentable(null); + } + + @Override + public List getSelectedPropositions(final Proposition defaultSelected) { + final List result = new LinkedList(); + for (ViewProposition singleProposition : this.propositionList) { + if (singleProposition.isChecked() || singleProposition.getRepresented() == defaultSelected) { + result.add(singleProposition.getRepresented()); + } + } + return result; + } + + @Override + public List getSelectedConnectables(final AbstractConnectable defaultSelected) { + final List list = new LinkedList(); + // REQUIREMENT: whole model is represented in the view + AbstractConnectable nextToCheck = this.propositionList.get(0).getRepresented(); + while (nextToCheck != null) { + // get checkable element + while (nextToCheck.getSuperOrdinatedRelation() != null) { + nextToCheck = nextToCheck.getSuperOrdinatedRelation(); + } + if (nextToCheck == defaultSelected || this.getRepresentative(nextToCheck).isChecked()) { + list.add(nextToCheck); + } + // get next element + nextToCheck = nextToCheck.getFollowingConnectableProposition(); + } + return list; + } + + /** + * Find the view representation of the given connectable (i.e. proposition or relation). + * + * @param target model element + * @return view representation + */ + public IConnectable getRepresentative(final AbstractConnectable target) { + if (target instanceof Proposition) { + return this.getRepresentative((Proposition) target); + } else if (target instanceof Relation) { + return this.getRepresentative((Relation) target); + } + // unsupported model object + throw new IllegalArgumentException(); + } + + /** + * Find the view representation of the given proposition. + * + * @param target model element + * @return view representation + */ + ViewProposition getRepresentative(final Proposition target) { + for (final ViewProposition singleProposition : this.propositionList) { + if (singleProposition.getRepresented() == target) { + return singleProposition; + } + } + return null; + } + + /** + * Find the view representation of the given relation. + * + * @param target model element + * @return view representation + */ + ViewRelation getRepresentative(final Relation target) { + return this.relationMap.get(target); + } + + @Override + public void handleSelectedCommentable(final AbstractCommentable newSelected) { + if (this.lastSelectedCommentable != null) { + final String newCommentToSet = this.commentArea.getText(); + final ICommentable lastSelectedModelElement = this.lastSelectedCommentable.getRepresented(); + if (!ComparisonUtil.isNullOrEmptyAwareEqual(lastSelectedModelElement.getComment(), newCommentToSet)) { + // store new comment in the last selected element + this.getModelHandler().setComment(lastSelectedModelElement, newCommentToSet); + this.lastSelectedCommentable.setToolTipText(newCommentToSet); + } + if (this.lastSelectedCommentable.isShowing()) { + // reset non-selection border of the last selected + this.lastSelectedCommentable.setDefaultBorder(); + } + } + this.lastSelectedCommentable = newSelected; + if (newSelected == null) { + this.commentArea.setText(null); + } else { + this.commentArea.setText(newSelected.getRepresented().getComment()); + newSelected.setCommentBorder(); + } + } + + + @Override + public boolean canUndo() { + return this.undoManager.canUndo(); + } + + @Override + public boolean canRedo() { + return this.undoManager.canRedo(); + } + + @Override + public void undo() { + // ensure that the any pending change is being reverted instead of the previously submit one + this.submitChangesToModel(); + this.undoInProgress = true; + try { + this.getModelHandler().resetModel(this.undoManager.undo()); + } finally { + this.undoInProgress = false; + } + } + + @Override + public void redo() { + // ignore any potentially pending change here (otherwise "Redo" might not be allowed anymore) + this.undoInProgress = true; + try { + this.getModelHandler().resetModel(this.undoManager.redo()); + } finally { + this.undoInProgress = false; + } + } + + @Override + public List> provideRelationTemplates() { + return this.relationProvider.provideRelationTemplates(); + } + + /** Make sure the headers for expanding/collapsing the relations (hide/show roles) are present and sized properly. */ + void resetHeaders() { + // remove old headers + this.contentHeaders.removeAll(); + // no relations mean no headers + final boolean showHeaders = this.levels > 1 && this.viewSettings.isShowingRelations(); + this.contentHeaders.setVisible(showHeaders); + if (!showHeaders) { + return; + } + // calculate width of each column + final Map maxColumnSize = new HashMap(); + final GridBagLayout contentLayout = (GridBagLayout) this.contentArea.getLayout(); + // check each component for its width and determine maximum per column + for (final Component singleComponent : this.contentArea.getComponents()) { + final int column = contentLayout.getConstraints(singleComponent).gridx; + final int componentWidth = singleComponent.getPreferredSize().width; + final int columnSize; + if (maxColumnSize.containsKey(column)) { + columnSize = Math.max(componentWidth, maxColumnSize.get(column)); + } else { + columnSize = componentWidth; + } + maxColumnSize.put(column, columnSize); + } + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.CENTER; + constraints.gridx = this.levels; + // no folding/collapsing for propositions + final boolean foldAll = this.foldedLevels.isEmpty(); + final HmxMessage messageKey = foldAll ? HmxMessage.MENU_FOLD_RELATION_ALL : HmxMessage.MENU_UNFOLD_RELATION_ALL; + final JButton foldAllButton = new JButton(messageKey.get()); + foldAllButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent event) { + AnalysisPanel.this.foldRelationRolesOnLevel(-1, foldAll); + } + }); + foldAllButton.setPreferredSize(new Dimension(maxColumnSize.get(this.levels), foldAllButton.getPreferredSize().height)); + this.contentHeaders.add(foldAllButton, constraints); + + final String foldToolTip = HmxMessage.MENU_FOLD_RELATION_LEVEL.get(); + final String unfoldToolTip = HmxMessage.MENU_UNFOLD_RELATION_LEVEL.get(); + // insert fold/collapse button for each relation level + for (int level = 1; level < this.levels; level++) { + final boolean fold = !this.foldedLevels.contains(level); + final JPanel headerPanel = new JPanel(); + final JCheckBox box = new JCheckBox(); + box.setSelected(fold); + box.setToolTipText(fold ? foldToolTip : unfoldToolTip); + final int levelIndex = level; + box.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent event) { + AnalysisPanel.this.foldRelationRolesOnLevel(levelIndex, fold); + } + }); + headerPanel.add(box, BorderLayout.CENTER); + constraints.gridx--; + // apply width of each column to its header + headerPanel.setPreferredSize(new Dimension(maxColumnSize.get(constraints.gridx), headerPanel.getPreferredSize().height)); + this.contentHeaders.add(headerPanel, constraints); + } + } + + /** + * Hide/show the associate roles on the {@link Relation} column at the given index. + * + * @param level + * single relation level to fold/unfold (targets all levels, when is {@code -1}) + * @param fold + * if the semantic roles of the indicated {@code level} should be hidden + */ + public void foldRelationRolesOnLevel(final int level, final boolean fold) { + final boolean onlySelectedLevel = -1 != level; + if (fold && onlySelectedLevel) { + if (this.foldedLevels.contains(level)) { + // nothing changed + return; + } + this.foldedLevels.add(level); + } else if (fold) { + for (int i = 0; i < this.levels; i++) { + this.foldedLevels.add(i); + } + } else if (onlySelectedLevel) { + this.foldedLevels.remove(level); + } else { + this.foldedLevels.clear(); + } + final GridBagLayout headerLayout = (GridBagLayout) this.contentHeaders.getLayout(); + for (final Component singleHeader : this.contentHeaders.getComponents()) { + final int currentLevel = this.levels - headerLayout.getConstraints(singleHeader).gridx; + if (singleHeader instanceof JCheckBox && level == currentLevel) { + final boolean folded = this.foldedLevels.contains(currentLevel); + final JCheckBox box = (JCheckBox) singleHeader; + if (box.isSelected() == folded) { + box.setSelected(!folded); + } + break; + } + } + this.refresh(); + } +} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisViewSettings.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisViewSettings.java new file mode 100644 index 0000000..d754649 --- /dev/null +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/AnalysisViewSettings.java @@ -0,0 +1,181 @@ +/* + Copyright (C) 2017 HermeneutiX.org + + This file is part of SciToS. + + SciToS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SciToS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SciToS. If not, see . + */ + +package org.hmx.scitos.hmx.view.swing.components; + +import org.hmx.scitos.hmx.core.option.HmxGeneralOption; + +/** + * Collection of independent view toggles for an {@link AnalysisPanel}. + */ +class AnalysisViewSettings implements IAnalysisViewSettings { + + /** Toggle: label fields of propositions. */ + private boolean showingPropositionLabels; + /** Toggle: syntactic functions of propositions to other propositions. */ + private boolean showingPropositionIndentations; + /** Toggle: semantic relations over propositions. */ + private boolean showingRelations; + /** Toggle: individual clause items in propositions. */ + private boolean showingClauseItems; + /** Toggle: syntactic translation fields of propositions. */ + private boolean showingSyntacticTranslations; + /** Toggle: semantic translation fields of propositions. */ + private boolean showingSemanticTranslations; + + /** + * Constructor: defaulting the view toggles to the "Syntactical Analysis" preset. + */ + AnalysisViewSettings() { + this.showingPropositionLabels = HmxGeneralOption.SHOW_PROPOSITION_LABELS.getValueAsBoolean(); + } + + /** + * Show individual clause items and indentation functions of propostions, but hide relations and semantical translations. + * + * @param preset view settings to apply (ignoring the label visibility if the given preset is + * @return self reference + */ + final AnalysisViewSettings applyViewPreset(final IAnalysisViewSettings preset) { + // the presets for the syntactical and semantical analyses should preserve the current label visibility + if (preset != IAnalysisViewSettings.SYNTACTICAL_ANALYSIS && preset != IAnalysisViewSettings.SEMANTICAL_ANALYSIS) { + this.setShowingPropositionLabels(preset.isShowingPropositionLabels()); + } + this.setShowingPropositionIndentations(preset.isShowingPropositionIndentations()); + this.setShowingRelations(preset.isShowingRelations()); + this.setShowingClauseItems(preset.isShowingClauseItems()); + this.setShowingSyntacticTranslations(preset.isShowingSyntacticTranslations()); + this.setShowingSemanticTranslations(preset.isShowingSemanticTranslations()); + return this; + } + + /** + * Check whether this collection of settings represents the given preset. + * + * @param preset settings preset to compare with + * @return whether this matches the given preset + */ + final boolean matchesPreset(final IAnalysisViewSettings preset) { + final boolean matchingLabelVisibility = this.isShowingPropositionLabels() == preset.isShowingPropositionLabels() + || preset == IAnalysisViewSettings.SYNTACTICAL_ANALYSIS || preset == IAnalysisViewSettings.SEMANTICAL_ANALYSIS; + final boolean result = matchingLabelVisibility + && this.isShowingPropositionIndentations() == preset.isShowingPropositionIndentations() + && this.isShowingRelations() == preset.isShowingRelations() + && this.isShowingClauseItems() == preset.isShowingClauseItems() + && this.isShowingSyntacticTranslations() == preset.isShowingSyntacticTranslations() + && this.isShowingSemanticTranslations() == preset.isShowingSemanticTranslations(); + return result; + } + + @Override + public boolean isShowingPropositionLabels() { + return this.showingPropositionLabels; + } + + /** + * Set view toggle for the label fields of propositions. + * + * @param show whether the label fields of propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingPropositionLabels(final boolean show) { + this.showingPropositionLabels = show; + return show; + } + + @Override + public boolean isShowingClauseItems() { + return this.showingClauseItems; + } + + /** + * Set view toggle for the individual clause items in propositions. + * + * @param show whether the individual clause items in propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingClauseItems(final boolean show) { + this.showingClauseItems = show; + return show; + } + + @Override + public boolean isShowingSyntacticTranslations() { + return this.showingSyntacticTranslations; + } + + /** + * Set view toggle for the syntactic translation fields of propositions. + * + * @param show whether the syntactic translation fields of propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingSyntacticTranslations(final boolean show) { + this.showingSyntacticTranslations = show; + return show; + } + + @Override + public boolean isShowingSemanticTranslations() { + return this.showingSemanticTranslations; + } + + /** + * Set view toggle for the semantic translation fields of propositions. + * + * @param show whether the semantic translation fields of propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingSemanticTranslations(final boolean show) { + this.showingSemanticTranslations = show; + return show; + } + + @Override + public boolean isShowingPropositionIndentations() { + return this.showingPropositionIndentations; + } + + /** + * Set view toggle for the syntactic functions of propositions to other propositions. + * + * @param show whether the syntactic functions of propostiions to other propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingPropositionIndentations(final boolean show) { + this.showingPropositionIndentations = show; + return show; + } + + @Override + public boolean isShowingRelations() { + return this.showingRelations; + } + + /** + * Set view toggle for the semantic relations over propositions. + * + * @param show whether the semantic relations over propositions should be shown + * @return the given view toggle value + */ + public boolean setShowingRelations(final boolean show) { + this.showingRelations = show; + return show; + } +} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/CombinedAnalysesPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/CombinedAnalysesPanel.java deleted file mode 100644 index f162e88..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/CombinedAnalysesPanel.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collections; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTextPane; -import javax.swing.ScrollPaneConstants; -import javax.swing.UIManager; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import org.hmx.scitos.core.UndoManager; -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.domain.ModelEvent; - -import org.hmx.scitos.domain.util.ComparisonUtil; -import org.hmx.scitos.hmx.core.HmxModelHandler; -import org.hmx.scitos.hmx.core.i18n.HmxMessage; -import org.hmx.scitos.hmx.core.option.HmxGeneralOption; -import org.hmx.scitos.hmx.domain.ICommentable; -import org.hmx.scitos.hmx.domain.ISemanticalRelationProvider; -import org.hmx.scitos.hmx.domain.model.AbstractConnectable; -import org.hmx.scitos.hmx.domain.model.Pericope; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.domain.model.RelationTemplate; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.hmx.view.swing.elements.AbstractCommentable; -import org.hmx.scitos.view.swing.components.ScaledLabel; -import org.hmx.scitos.view.swing.components.ScaledTextPane; -import org.hmx.scitos.view.swing.util.VTextIcon; - -/** - * The view representation of a {@link Pericope} in the analysis mode – containing both the syntactical and semantical analysis. - */ -public final class CombinedAnalysesPanel extends JPanel implements IPericopeView, ModelChangeListener { - - /** The represented project's model handler instance. */ - private final HmxModelHandler modelHandler; - /** - * The provider of available semantical {@link RelationTemplate}s, to be offered via the elements' context menus. - */ - private final ISemanticalRelationProvider relationProvider; - /** The undo manager for the whole model. */ - private final UndoManager undoManager; - /** Flag indicating that an un-do or re-do operation is currently in progress. */ - private boolean undoInProgress = false; - - /** The button to switch between the syntactical and semantical analysis. */ - private final JButton switchButton; - /** - * The vertical label for the {@link #switchButton} to switch from the syntactical to the semantical analysis. - */ - private final VTextIcon semButtonIcon; - /** - * The vertical label for the {@link #switchButton} to switch from the semantical to the syntactical analysis. - */ - private final VTextIcon synButtonIcon; - /** The view component representing the semantical analysis. */ - private final SemAnalysisPanel semAnalysisView; - /** The view component representing the syntactical analysis. */ - private final SynAnalysisPanel synAnalysisView; - /** - * The input area at the bottom of the view, allowing the display and modification of a selected element's comment. - */ - private final JTextPane commentArea; - - /** - * Flag indicating whether the label fields of propositions should be displayed or not. - */ - private boolean showingPropositionLabels = HmxGeneralOption.SHOW_PROPOSITION_LABELS.getValueAsBoolean(); - /** - * Flag indicating whether the translation fields of propositions should be displayed or not. - */ - private boolean showingPropositionTranslations = HmxGeneralOption.SHOW_PROPOSITION_TRANSLATIONS.getValueAsBoolean(); - /** - * The most recently selected commentable model element currently associated with the {@link #commentArea}. - */ - private AbstractCommentable lastSelectedCommentable; - - /** - * Constructor. - * - * @param modelHandler - * the represented project's model handler instance - * @param relationProvider - * the provider of available semantical {@link RelationTemplate}s, to be offered via the elements' context menus - */ - public CombinedAnalysesPanel(final HmxModelHandler modelHandler, final ISemanticalRelationProvider relationProvider) { - super(new GridBagLayout()); - this.modelHandler = modelHandler; - this.relationProvider = relationProvider; - this.undoManager = new UndoManager(this.modelHandler.getModel()); - this.addAncestorListener(new AncestorListener() { - @Override - public void ancestorAdded(final AncestorEvent event) { - // ensure logging of model change events by the UndoManager - modelHandler.addModelChangeListener(CombinedAnalysesPanel.this); - } - - @Override - public void ancestorRemoved(final AncestorEvent event) { - /* - * unregister UndoManager as long as nothing is shown (nothing can be changed); this is to avoid multiple of these listeners if the - * respective tabs are being closed and re-opened repeatedly - */ - modelHandler.removeModelChangeListener(CombinedAnalysesPanel.this); - } - - @Override - public void ancestorMoved(final AncestorEvent event) { - // we don't care about any movement - } - }); - - this.setBorder(null); - // initialize the commentArea to be reachable by commentable components - this.commentArea = new ScaledTextPane(); - // build the analysis views representing the pericope - this.semAnalysisView = new SemAnalysisPanel(this); - this.synAnalysisView = new SynAnalysisPanel(this); - - this.switchButton = new JButton() { - - @Override - public void updateUI() { - super.updateUI(); - this.setFont(UIManager.getFont("Button.font")); - } - }; - this.switchButton.setName("Switch Analysis Button"); - // initialize the possible button icons - this.semButtonIcon = new VTextIcon(this.switchButton, HmxMessage.ANALYSIS_SEMANTICAL_BUTTON.get(), VTextIcon.Rotate.NONE); - this.synButtonIcon = new VTextIcon(this.switchButton, HmxMessage.ANALYSIS_SYNTACTICAL_BUTTON.get(), VTextIcon.Rotate.NONE); - - // default: always start with the syntactical analysis - this.switchButton.setIcon(this.semButtonIcon); - this.initView(); - this.synAnalysisView.activate(); - } - - /** - * Initialize the whole layout. - */ - private void initView() { - // arrange the analysis views and the button for switching between them - final JPanel topArea = new JPanel(new GridBagLayout()); - - final GridBagConstraints doubleSpan = new GridBagConstraints(); - doubleSpan.fill = GridBagConstraints.BOTH; - doubleSpan.weightx = 1; - doubleSpan.weighty = 1; - // add the semantical analysis to the left - doubleSpan.gridx = 0; - doubleSpan.gridy = 0; - topArea.add(this.semAnalysisView, doubleSpan); - // add the button for switching between the analysis to the mid - this.switchButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(final ActionEvent event) { - CombinedAnalysesPanel.this.changeActiveAnalysisView(); - } - }); - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.VERTICAL; - constraints.weighty = 1; - constraints.gridx = 1; - constraints.gridy = 0; - topArea.add(this.switchButton, constraints); - - // add the syntactical analysis to the right - doubleSpan.gridx = 2; - doubleSpan.gridy = 0; - topArea.add(this.synAnalysisView, doubleSpan); - // add the comment area for both views - final JPanel commentPanel = new JPanel(new GridBagLayout()); - // initialize spacings - final int sideSpacing = this.switchButton.getPreferredSize().width; - commentPanel.setBorder(BorderFactory.createEmptyBorder(0, sideSpacing, 10, sideSpacing)); - final JLabel topicLabel = new ScaledLabel(HmxMessage.ANALYSIS_COMMENT_TOPIC.get()); - topicLabel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5)); - commentPanel.add(topicLabel); - this.commentArea.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5)); - final JScrollPane scrollableComment = new JScrollPane(this.commentArea); - scrollableComment.setBorder(BorderFactory.createLoweredBevelBorder()); - scrollableComment.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - doubleSpan.gridx = 0; - doubleSpan.gridy = 1; - commentPanel.add(scrollableComment, doubleSpan); - commentPanel.setPreferredSize(new Dimension(1, 80)); - - final JSplitPane splitArea = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topArea, commentPanel); - splitArea.setBorder(null); - splitArea.setResizeWeight(1); - this.add(splitArea, doubleSpan); - } - - @Override - public void modelChanged(final ModelEvent event) { - // ignore change event thrown by the own undo/redo action - if (!this.undoInProgress) { - this.undoManager.undoableEditHappened(this.modelHandler.getModel()); - } - } - - /** - * Change the active analysis view by setting their visibility to make sure that only one analysis view is visible; and clear the shown comment. - */ - void changeActiveAnalysisView() { - // clear comment area - this.handleSelectedCommentable(null); - // make sure only one analysis view is visible at the end - if (this.semAnalysisView.isShowing()) { - this.synAnalysisView.activate(); - this.semAnalysisView.deactivate(); - this.switchButton.setIcon(this.semButtonIcon); - } else { - this.semAnalysisView.activate(); - this.synAnalysisView.deactivate(); - this.switchButton.setIcon(this.synButtonIcon); - } - } - - @Override - public List getSelectedConnectables(final AbstractConnectable defaultSelected) { - if (this.semAnalysisView.isShowing()) { - return this.semAnalysisView.getChecked(defaultSelected); - } - if (defaultSelected == null) { - return Collections.emptyList(); - } - return Collections.singletonList(defaultSelected); - } - - @Override - public List getSelectedPropositions(final Proposition defaultSelected) { - if (this.synAnalysisView.isVisible()) { - return this.synAnalysisView.getChecked(defaultSelected); - } - if (defaultSelected == null) { - return Collections.emptyList(); - } - return Collections.singletonList(defaultSelected); - } - - @Override - public void handleSelectedCommentable(final AbstractCommentable newSelected) { - if (this.lastSelectedCommentable != null) { - final String newCommentToSet = this.commentArea.getText(); - final ICommentable lastSelectedModelElement = this.lastSelectedCommentable.getRepresented(); - if (!ComparisonUtil.isNullOrEmptyAwareEqual(lastSelectedModelElement.getComment(), newCommentToSet)) { - // store new comment in the last selected element - this.getModelHandler().setComment(lastSelectedModelElement, newCommentToSet); - this.lastSelectedCommentable.setToolTipText(newCommentToSet); - } - if (this.lastSelectedCommentable.isShowing()) { - // reset non-selection border of the last selected - this.lastSelectedCommentable.setDefaultBorder(); - } - } - this.lastSelectedCommentable = newSelected; - if (newSelected == null) { - this.commentArea.setText(null); - } else { - this.commentArea.setText(newSelected.getRepresented().getComment()); - newSelected.setCommentBorder(); - } - } - - @Override - public HmxModelHandler getModelHandler() { - return this.modelHandler; - } - - @Override - public void submitChangesToModel() { - final AbstractAnalysisPanel activeAnalysisView = this.getActiveAnalysisView(); - if (activeAnalysisView != null) { - activeAnalysisView.submitChangesToModel(); - } - // also take care of any newly entered comment specifically - this.handleSelectedCommentable(null); - } - - /** - * Fully rebuild the currently displayed representation of the {@link Pericope}. - */ - @Override - public void refresh() { - final AbstractAnalysisPanel activeAnalysisView = this.getActiveAnalysisView(); - if (activeAnalysisView != null) { - activeAnalysisView.repaintPericope(); - } - } - - @Override - public boolean isShowingPropositionLabels() { - return this.showingPropositionLabels; - } - - @Override - public boolean isShowingPropositionTranslations() { - return this.showingPropositionTranslations; - } - - /** - * Toggle the visibility of the label fields for all propositions. This causes a full rebuild of the displayed Pericope. - * - * @see #refresh() - */ - public void togglePropositionLabelVisibility() { - this.showingPropositionLabels = !this.showingPropositionLabels; - this.refresh(); - } - - /** - * Toggle the visibility of the translation fields for all propositions. This causes a full rebuild of the displayed Pericope. - * - * @see #refresh() - */ - public void togglePropositionTranslationVisibility() { - this.showingPropositionTranslations = !this.showingPropositionTranslations; - this.refresh(); - } - - /** - * Determine the currently active analysis view (either {@link #synAnalysisView} or {@link #semAnalysisView}). - * - * @return currently active/displayed analysisView - */ - private AbstractAnalysisPanel getActiveAnalysisView() { - if (this.synAnalysisView.isShowing()) { - return this.synAnalysisView; - } - if (this.semAnalysisView.isShowing()) { - return this.semAnalysisView; - } - return null; - } - - @Override - public boolean canUndo() { - return this.undoManager.canUndo(); - } - - @Override - public boolean canRedo() { - return this.undoManager.canRedo(); - } - - @Override - public void undo() { - // ensure that the any pending change is being reverted instead of the previously submit one - this.submitChangesToModel(); - this.undoInProgress = true; - try { - this.getModelHandler().resetModel(this.undoManager.undo()); - } finally { - this.undoInProgress = false; - } - } - - @Override - public void redo() { - // ignore any potentially pending change here (otherwise "Redo" might not be allowed anymore) - this.undoInProgress = true; - try { - this.getModelHandler().resetModel(this.undoManager.redo()); - } finally { - this.undoInProgress = false; - } - } - - @Override - public List> provideRelationTemplates() { - return this.relationProvider.provideRelationTemplates(); - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/IAnalysisViewSettings.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/IAnalysisViewSettings.java new file mode 100644 index 0000000..561509e --- /dev/null +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/IAnalysisViewSettings.java @@ -0,0 +1,144 @@ +/* + Copyright (C) 2017 HermeneutiX.org + + This file is part of SciToS. + + SciToS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SciToS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SciToS. If not, see . + */ + +package org.hmx.scitos.hmx.view.swing.components; + +/** + * Wrapper for a number of view settings. + */ +public interface IAnalysisViewSettings { + + /** Preset: showing all details. */ + IAnalysisViewSettings SHOW_ALL = new ReadOnlyViewSettings(true, true, true, true, true, true); + /** Preset: syntactical analysis. */ + IAnalysisViewSettings SYNTACTICAL_ANALYSIS = new ReadOnlyViewSettings(true, true, false, true, true, false); + /** Preset: semantical analysis. */ + IAnalysisViewSettings SEMANTICAL_ANALYSIS = new ReadOnlyViewSettings(true, false, true, false, false, true); + + /** + * Get view toggle for the label fields of propositions. + * + * @return whether the label fields of propositions should be shown + */ + boolean isShowingPropositionLabels(); + + /** + * Get view toggle for the individual clause items in propositions. + * + * @return whether the individual clause items in propositions should be shown + */ + boolean isShowingClauseItems(); + + /** + * Get view toggle for the syntactic translation fields of propositions. + * + * @return whether the syntactic translation fields of propositions should be shown + */ + boolean isShowingSyntacticTranslations(); + + /** + * Get view toggle for the semantic translation fields of propositions. + * + * @return whether the semantic translation fields of propositions should be shown + */ + boolean isShowingSemanticTranslations(); + + /** + * Get view toggle for the syntactic functions of propositions to other propositions. + * + * @return whether the syntactic functions of propostiions to other propositions should be shown + */ + boolean isShowingPropositionIndentations(); + + /** + * Get view toggle for the semantic relations over propositions. + * + * @return whether the semantic relations over propositions should be shown + */ + boolean isShowingRelations(); + + /** + * Read-only implementation of the {@link IAnalysisViewSettings} interface, for offering unmodifiable presets. + */ + class ReadOnlyViewSettings implements IAnalysisViewSettings { + + /** View Setting: label fields of propositions. */ + private final boolean showingPropositionLabels; + /** View Setting: syntactic functions of propositions to other propositions. */ + private final boolean showingPropositionIndentations; + /** View Setting: semantic relations over propositions. */ + private final boolean showingRelations; + /** View Setting: individual clause items in propositions. */ + private final boolean showingClauseItems; + /** View Setting: syntactic translation fields of propositions. */ + private final boolean showingSyntacticTranslations; + /** View Setting: semantic translation fields of propositions. */ + private final boolean showingSemanticTranslations; + + /** + * Constructor. + * + * @param showingPropositionLabels preset value: label fields of propositions + * @param showingPropositionIndentations preset value: syntactic functions of propositions to other propositions + * @param showingRelations preset value: semantic relations over propositions + * @param showingClauseItems preset value: individual clause items in propositions + * @param showingSyntacticTranslations preset value: syntactic translation fields of propositions + * @param showingSemanticTranslations preset value: semantic translation fields of propositions + */ + ReadOnlyViewSettings(final boolean showingPropositionLabels, final boolean showingPropositionIndentations, final boolean showingRelations, + final boolean showingClauseItems, final boolean showingSyntacticTranslations, final boolean showingSemanticTranslations) { + this.showingPropositionLabels = showingPropositionLabels; + this.showingPropositionIndentations = showingPropositionIndentations; + this.showingRelations = showingRelations; + this.showingClauseItems = showingClauseItems; + this.showingSyntacticTranslations = showingSyntacticTranslations; + this.showingSemanticTranslations = showingSemanticTranslations; + } + + @Override + public boolean isShowingPropositionLabels() { + return this.showingPropositionLabels; + } + + @Override + public boolean isShowingPropositionIndentations() { + return this.showingPropositionIndentations; + } + + @Override + public boolean isShowingRelations() { + return this.showingRelations; + } + + @Override + public boolean isShowingClauseItems() { + return this.showingClauseItems; + } + + @Override + public boolean isShowingSyntacticTranslations() { + return this.showingSyntacticTranslations; + } + + @Override + public boolean isShowingSemanticTranslations() { + return this.showingSemanticTranslations; + } + } +} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemAnalysisPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemAnalysisPanel.java deleted file mode 100755 index 010410d..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemAnalysisPanel.java +++ /dev/null @@ -1,538 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.ComponentOrientation; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingUtilities; -import javax.swing.border.MatteBorder; - -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.domain.util.CollectionUtil; -import org.hmx.scitos.hmx.core.i18n.HmxMessage; -import org.hmx.scitos.hmx.domain.model.AbstractConnectable; -import org.hmx.scitos.hmx.domain.model.Pericope; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.domain.model.Relation; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.hmx.view.swing.elements.IConnectable; -import org.hmx.scitos.hmx.view.swing.elements.SemProposition; -import org.hmx.scitos.hmx.view.swing.elements.SemRelation; -import org.hmx.scitos.hmx.view.swing.elements.SemRelationExtender; - -/** - * Semantical analysis view displaying the semantical structured analysis consisting of {@link Proposition}s and {@link Relation}s. This is - * disregarding the syntactical functions, indentations, individual ClauseItems and syntactical translations in the {@link Proposition}s. Instead, - * offering the opportunity to create, edit and remove {@link Relation}s. - */ -public final class SemAnalysisPanel extends AbstractAnalysisPanel { - - /** - * The current maximum depth of the represented tree of {@link Relation}s. - */ - private int levels = 0; - /** The single main component allowing everything to be scrolled. */ - final JScrollPane scrollPane; - /** The actual container for view elements. */ - private final JPanel contentArea = new JPanel(new GridBagLayout()); - /** - * The header bar allowing to expand/collapse {@link Relation} columns by toggling the roles' visibility. - */ - final JPanel contentHeaders = new JPanel(new GridBagLayout()) { - - @Override - public void updateUI() { - if (SemAnalysisPanel.this.contentHeaders != null) { - // reset to apply potentially changed scale factor - SemAnalysisPanel.this.resetHeaders(); - } - } - }; - /** The model change listener responsible for keeping this panel up to date as long as it is active. */ - private final SemControl listener; - /** - * The indices of currently collapsed {@link Relation} columns, i.e. where the associate roles are currently hidden to reduce required horizontal - * space. - */ - private final Set foldedLevels = new HashSet(); - /** - * Complete list of currently contained view components representing the {@link Pericope}'s {@link Proposition}s. - */ - private List propositionList; - /** - * Complete mapping of {@link Relation}s to their representing view components. - */ - private Map relationMap; - - /** - * Constructor. - * - * @param viewReference - * super ordinated view this panel belongs to - */ - public SemAnalysisPanel(final IPericopeView viewReference) { - super(viewReference, new GridLayout(0, 1)); - this.setVisible(false); - this.listener = new SemControl(this); - this.scrollPane = this.initView(); - } - - @Override - protected ModelChangeListener getModelChangeListener() { - return this.listener; - } - - /** - * Initialize the general layout and position of the content to display. - * - * @return the {@link JScrollPane} containing the whole content - */ - private JScrollPane initView() { - // make the whole analysis view scrollable - final JPanel background = new JPanel(new GridBagLayout()); - // initialize content area - final GridBagConstraints mainConstraints = new GridBagConstraints(); - mainConstraints.anchor = GridBagConstraints.FIRST_LINE_END; - mainConstraints.fill = GridBagConstraints.BOTH; - mainConstraints.gridx = 1; - mainConstraints.gridy = 0; - background.add(this.contentArea, mainConstraints); - // make sure it is always at the top - final GridBagConstraints bottomSpace = new GridBagConstraints(); - bottomSpace.fill = GridBagConstraints.VERTICAL; - bottomSpace.weighty = 1; - bottomSpace.gridx = 1; - bottomSpace.gridy = 1; - background.add(new JPanel(null), bottomSpace); - // make sure it is always on the right - final GridBagConstraints leftSpace = new GridBagConstraints(); - leftSpace.fill = GridBagConstraints.HORIZONTAL; - leftSpace.weightx = 1; - leftSpace.gridx = 0; - leftSpace.gridy = 0; - background.add(new JPanel(null), leftSpace); - // wrap the headers to get equal behavior - final JPanel headerView = new JPanel(new GridBagLayout()); - headerView.add(new JPanel(null), leftSpace); - headerView.add(this.contentHeaders, mainConstraints); - headerView.setBorder(new MatteBorder(0, 0, 1, 0, Color.BLACK)); - - final ComponentOrientation orientation; - if (this.getViewReference().getModelHandler().getModel().isLeftToRightOriented()) { - orientation = ComponentOrientation.LEFT_TO_RIGHT; - } else { - orientation = ComponentOrientation.RIGHT_TO_LEFT; - } - background.setComponentOrientation(orientation); - this.contentArea.setComponentOrientation(orientation); - headerView.setComponentOrientation(orientation); - this.contentHeaders.setComponentOrientation(orientation); - - final JScrollPane scrollablePane = new JScrollPane(background); - scrollablePane.setColumnHeaderView(headerView); - scrollablePane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - this.add(scrollablePane); - return scrollablePane; - } - - /** - * Hide/show the associate roles on the {@link Relation} column at the given index. - * - * @param level - * single relation level to fold/unfold (targets all levels, when is {@code -1}) - * @param fold - * if the semantic roles of the indicated {@code level} should be hidden - */ - public void foldRelationRolesOnLevel(final int level, final boolean fold) { - final boolean onlySelectedLevel = -1 != level; - if (fold && onlySelectedLevel) { - if (this.foldedLevels.contains(level)) { - // nothing changed - return; - } - this.foldedLevels.add(level); - } else if (fold) { - for (int i = 0; i < this.levels; i++) { - this.foldedLevels.add(i); - } - } else if (onlySelectedLevel) { - this.foldedLevels.remove(level); - } else { - this.foldedLevels.clear(); - } - final GridBagLayout headerLayout = (GridBagLayout) this.contentHeaders.getLayout(); - for (final Component singleHeader : this.contentHeaders.getComponents()) { - final int currentLevel = this.levels - headerLayout.getConstraints(singleHeader).gridx; - if (singleHeader instanceof JCheckBox && level == currentLevel) { - final boolean folded = this.foldedLevels.contains(currentLevel); - final JCheckBox box = (JCheckBox) singleHeader; - if (box.isSelected() == folded) { - box.setSelected(!folded); - } - break; - } - } - this.repaintPericope(); - } - - @Override - public void deactivate() { - super.deactivate(); - this.propositionList = null; - this.relationMap = null; - } - - @Override - public void repaintPericope() { - // remember vertical position - final int verticalPosition = this.scrollPane.getVerticalScrollBar().getValue(); - // clear view - this.getViewReference().submitChangesToModel(); - this.scrollPane.setVisible(false); - this.contentArea.removeAll(); - // get the currently used origin text font - this.propositionList = new ArrayList(); - // fill the propositionList - for (final Proposition singleTopLevelProposition : this.getViewReference().getModelHandler().getModel().getText()) { - this.addSemPropositionToList(singleTopLevelProposition); - } - this.levels = this.calculateLevels(); - // show pericope - this.displayPropositions(); - this.displayRelations(); - this.resetHeaders(); - // reset vertical position - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - SemAnalysisPanel.this.scrollPane.setVisible(true); - SemAnalysisPanel.this.scrollPane.getVerticalScrollBar().setValue(verticalPosition); - } - }); - } - - /** - * Transfer the {@link SemProposition}s contained in the {@link #propositionList} to the displayed view. - */ - private void displayPropositions() { - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridx = Math.max(1, this.levels); - constraints.gridy = 0; - for (final SemProposition singleProposition : this.propositionList) { - if (singleProposition.getRepresented().getSuperOrdinatedRelation() != null) { - singleProposition.setCheckBoxVisible(false); - } - this.contentArea.add(singleProposition, constraints); - constraints.gridy++; - } - } - - /** - * Build the {@link #relationMap} and display it; assuming the already created {@link #propositionList}. - */ - private void displayRelations() { - this.relationMap = new HashMap(); - SemProposition singleProposition = this.propositionList.get(0); - while (singleProposition != null) { - Relation singleRelation = singleProposition.getRepresented().getSuperOrdinatedRelation(); - if (singleRelation == null) { - final Proposition follower = singleProposition.getRepresented().getFollowingConnectableProposition(); - if (follower == null) { - break; - } - singleProposition = SemControl.getRepresentative(this, follower); - } else { - // get the highest relation over the singleProposition - while (singleRelation.getSuperOrdinatedRelation() != null) { - singleRelation = singleRelation.getSuperOrdinatedRelation(); - } - // add highest and all of its subordinated relations in map - this.insertRelationTree(singleRelation); - final Proposition follower = singleRelation.getLastPropositionContained().getFollowingConnectableProposition(); - if (follower == null) { - break; - } - singleProposition = SemControl.getRepresentative(this, follower); - } - } - } - - /** - * Display the specified {@link Relation} and all of its subordinated {@link AbstractConnectable}s. - * - * @param relation - * {@link Relation} to display - */ - private void insertRelationTree(final Relation relation) { - // insert all subordinated relations first - for (final AbstractConnectable singleAssociate : relation) { - if (singleAssociate instanceof Relation) { - this.insertRelationTree((Relation) singleAssociate); - } - } - final SemRelation viewRepresentative = new SemRelation(this.getViewReference(), this, relation, this.foldedLevels); - // insert the relation itself in the map - this.relationMap.put(relation, viewRepresentative); - // build constraints - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.BOTH; - constraints.gridheight = (int) (viewRepresentative.getLastGridY() - viewRepresentative.getFirstGridY() + 1); - constraints.gridx = this.levels - viewRepresentative.getDepth(); - constraints.gridy = (int) (viewRepresentative.getFirstGridY() - 0.5); - // display - this.contentArea.add(viewRepresentative, constraints); - viewRepresentative.setVisible(false); - viewRepresentative.setVisible(true); - // extend lines if there is a gap between relation and its associates - for (final AbstractConnectable singleAssociate : relation) { - int depth = viewRepresentative.getDepth() - 1; - final IConnectable associateRepresentative = SemControl.getRepresentative(this, singleAssociate); - final double connectY = associateRepresentative.getConnectY(); - if ((connectY % 1) == 0) { - constraints.gridheight = 2; - } else { - constraints.gridheight = 1; - } - constraints.gridy = (int) (connectY - 0.5); - while (depth > associateRepresentative.getDepth()) { - constraints.gridx = this.levels - depth; - this.contentArea.add(new SemRelationExtender(), constraints); - depth--; - } - } - } - - /** - * Add the specified {@link Proposition} to the list of {@link SemProposition}s WITHOUT adding it to the view. - * - * @param proposition - * {@link Proposition} to add to list - */ - private void addSemPropositionToList(final Proposition proposition) { - // first: add all prior children - final List priorChildren = proposition.getPriorChildren(); - if (priorChildren != null) { - for (final Proposition singlePriorChild : priorChildren) { - this.addSemPropositionToList(singlePriorChild); - } - } - // second: add the proposition itself - final SemProposition viewProposition = new SemProposition(this.getViewReference(), this, proposition); - if (this.propositionList == null) { - this.propositionList = new ArrayList(); - } - this.propositionList.add(viewProposition); - final Proposition partBeforeArrow = proposition.getPartBeforeArrow(); - if (partBeforeArrow != null) { - final SemProposition viewPartBeforeArrow = SemControl.getRepresentative(this, partBeforeArrow); - // show arrows - final int listSize = this.propositionList.size(); - final int beforeArrowPos = CollectionUtil.indexOfInstance(this.propositionList, viewPartBeforeArrow); - // count number of arrows to set - int arrowCount = listSize - beforeArrowPos - 1; - // ignore partAfterArrows - for (int i = beforeArrowPos + 1; i < listSize; i++) { - if (this.propositionList.get(i).getRepresented().getPartBeforeArrow() != null) { - arrowCount--; - } - } - // show arrows in part before arrow - viewPartBeforeArrow.setRightArrowCount(arrowCount); - // show arrows in target - viewProposition.setLeftArrowCount(arrowCount); - } - // third: add all later children - final List laterChildren = proposition.getLaterChildren(); - if (laterChildren != null) { - for (final Proposition singleLaterChild : laterChildren) { - this.addSemPropositionToList(singleLaterChild); - } - } - // finally: add the part after arrow - final Proposition partAfterArrow = proposition.getPartAfterArrow(); - if (partAfterArrow != null) { - this.addSemPropositionToList(partAfterArrow); - } - } - - @Override - public void submitChangesToModel() { - // only the propositions might have any pending changes (e.g. the label and translation fields) - if (this.propositionList != null) { - for (final SemProposition singleProposition : this.propositionList) { - singleProposition.submitChangesToModel(); - } - } - } - - /** - * Expose a mutable copy of the internal list of displayed {@link SemProposition}s. - * - * @return list containing all {@link Proposition} components in this view - */ - public List getPropositionList() { - if (this.propositionList == null) { - return null; - } - return new ArrayList(this.propositionList); - } - - /** - * Calculate the maximum number of super ordinated {@link Relation}s. - * - * @return calculated maximum level - */ - private int calculateLevels() { - int max = 0; - for (final SemProposition singleProposition : this.propositionList) { - Relation singleSuperordinated = singleProposition.getRepresented().getSuperOrdinatedRelation(); - int depth; - for (depth = 0; singleSuperordinated != null; depth++) { - singleSuperordinated = singleSuperordinated.getSuperOrdinatedRelation(); - } - max = Math.max(max, depth); - } - return (max + 1); - } - - /** - * Expose a mutable copy of the mapping of displayed {@link Relation} and their respective components. - * - * @return map containing all relations and their representations - */ - public Map getRelationMap() { - if (this.relationMap == null) { - return null; - } - return new HashMap(this.relationMap); - } - - /** - * Collect all currently checked {@link Relation}s and/or {@link Proposition}s in the right order. - * - * @param clicked - * single element to include in the result list (regardless of its checked state) - * @return list containing all checked elements sorted from top to bottom - */ - public List getChecked(final AbstractConnectable clicked) { - final List list = new LinkedList(); - // REQUIREMENT: whole model is represented in the view - AbstractConnectable nextToCheck = this.propositionList.get(0).getRepresented(); - while (nextToCheck != null) { - // get checkable element - while (nextToCheck.getSuperOrdinatedRelation() != null) { - nextToCheck = nextToCheck.getSuperOrdinatedRelation(); - } - if (nextToCheck == clicked || SemControl.getRepresentative(this, nextToCheck).isChecked()) { - list.add(nextToCheck); - } - // get next element - nextToCheck = nextToCheck.getFollowingConnectableProposition(); - } - return list; - } - - /** Make sure the headers for expanding/collapsing the relations (hide/show roles) are present and sized properly. */ - public void resetHeaders() { - // remove old headers - this.contentHeaders.removeAll(); - if (this.levels < 2) { - // no relations mean no headers - this.contentHeaders.setVisible(false); - return; - } - this.contentHeaders.setVisible(true); - // calculate width of each column - final Map maxColumnSize = new HashMap(); - final GridBagLayout contentLayout = (GridBagLayout) this.contentArea.getLayout(); - // check each component for its width and determine maximum per column - for (final Component singleComponent : this.contentArea.getComponents()) { - final int column = contentLayout.getConstraints(singleComponent).gridx; - int columnSize = singleComponent.getPreferredSize().width; - if (maxColumnSize.containsKey(column)) { - columnSize = Math.max(columnSize, maxColumnSize.get(column)); - } - maxColumnSize.put(column, columnSize); - } - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.CENTER; - constraints.gridx = this.levels; - // no folding/collapsing for propositions - final boolean foldAll = this.foldedLevels.isEmpty(); - final HmxMessage messageKey = foldAll ? HmxMessage.MENU_FOLD_RELATION_ALL : HmxMessage.MENU_UNFOLD_RELATION_ALL; - final JButton foldAllButton = new JButton(messageKey.get()); - foldAllButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(final ActionEvent event) { - SemAnalysisPanel.this.foldRelationRolesOnLevel(-1, foldAll); - } - }); - foldAllButton.setPreferredSize(new Dimension(maxColumnSize.get(this.levels), foldAllButton.getPreferredSize().height)); - this.contentHeaders.add(foldAllButton, constraints); - - final String foldToolTip = HmxMessage.MENU_FOLD_RELATION_LEVEL.get(); - final String unfoldToolTip = HmxMessage.MENU_UNFOLD_RELATION_LEVEL.get(); - // insert fold/collapse button for each relation level - for (int level = 1; level < this.levels; level++) { - final boolean fold = !this.foldedLevels.contains(level); - final JPanel headerPanel = new JPanel(); - final JCheckBox box = new JCheckBox(); - box.setSelected(fold); - box.setToolTipText(fold ? foldToolTip : unfoldToolTip); - final int levelIndex = level; - box.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(final ActionEvent event) { - SemAnalysisPanel.this.foldRelationRolesOnLevel(levelIndex, fold); - } - }); - headerPanel.add(box, BorderLayout.CENTER); - constraints.gridx--; - // apply width of each column to its header - headerPanel.setPreferredSize(new Dimension(maxColumnSize.get(constraints.gridx), headerPanel.getPreferredSize().height)); - this.contentHeaders.add(headerPanel, constraints); - } - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemControl.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemControl.java deleted file mode 100755 index 5705cd2..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SemControl.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.util.List; - -import javax.swing.SwingUtilities; - -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.domain.ModelEvent; -import org.hmx.scitos.hmx.domain.model.AbstractConnectable; -import org.hmx.scitos.hmx.domain.model.ClauseItem; -import org.hmx.scitos.hmx.domain.model.Pericope; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.domain.model.Relation; -import org.hmx.scitos.hmx.view.swing.elements.IConnectable; -import org.hmx.scitos.hmx.view.swing.elements.SemProposition; -import org.hmx.scitos.hmx.view.swing.elements.SemRelation; - -/** - * Listener for the {@link SemAnalysisPanel} to react on changed model elements. - */ -public final class SemControl implements ModelChangeListener { - - /** targeted semantical analysis view. */ - final SemAnalysisPanel semArea; - - /** - * Constructor: storing the targeted semantical analysis view to display the listened changes in. - * - * @param panel - * targeted semantical analysis view - */ - SemControl(final SemAnalysisPanel panel) { - this.semArea = panel; - } - - /** - * Create the listening functions for the defined {@link SemAnalysisPanel}, responsible for the whole handling of event representing a change in - * the model. - * - * @param event - * thrown {@link ModelEvent} containing the changed model element - */ - @Override - public void modelChanged(final ModelEvent event) { - final Object target = event.getTarget(); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - if (target instanceof Pericope || target instanceof Relation) { - // request whole rebuild - SemControl.this.semArea.repaintPericope(); - } else if (target instanceof Proposition) { - SemControl.this.refreshProposition((Proposition) target); - } else if (target instanceof ClauseItem) { - SemControl.this.refreshProposition(((ClauseItem) target).getParent()); - } - // the target should be no instance of another class - } - }); - } - - /** - * Handle a {@link ModelEvent} containing a {@link Proposition}. - * - * @param target - * proposition to refresh in view - */ - void refreshProposition(final Proposition target) { - final SemProposition representative = SemControl.getRepresentative(this.semArea, target); - if (representative == null) { - // edited proposition currently not displayed - return; - } - representative.refreshLabelText(); - representative.refreshOriginText(); - representative.refreshTranslation(); - representative.refreshComment(); - representative.setVisible(false); - representative.setVisible(true); - this.semArea.resetHeaders(); - } - - /** - * Get the view representation ({@link SemProposition}/{@link SemRelation}) of the specified model object ({@link Proposition}/{@link Relation}). - * - * @param semArea - * analysis view to search in - * @param target - * {@link Proposition}/{@link Relation} to look for - * @return view component ({@link SemProposition}/ {@link SemRelation}) representing target - */ - public static IConnectable getRepresentative(final SemAnalysisPanel semArea, final AbstractConnectable target) { - if (target instanceof Proposition) { - return SemControl.getRepresentative(semArea, (Proposition) target); - } else if (target instanceof Relation) { - return SemControl.getRepresentative(semArea, (Relation) target); - } - // unsupported model object - throw new IllegalArgumentException(); - } - - /** - * Get the representing view component for the given {@link Proposition}. - * - * @param semArea - * analysis view to search in - * @param target - * {@link Proposition} to look for - * @return {@link SemProposition} representing target - */ - public static SemProposition getRepresentative(final SemAnalysisPanel semArea, final Proposition target) { - final List viewPropositions = semArea.getPropositionList(); - for (final SemProposition singleViewProposition : viewPropositions) { - if (target == singleViewProposition.getRepresented()) { - // found representative in the syntactical analysis view - return singleViewProposition; - } - } - // target does not exist in the syntactical analysis view - return null; - } - - /** - * Get the representation of the specified {@link Relation} in the semantical analysis view. - * - * @param semArea - * analysis view to search in - * @param target - * {@link Relation} to look for - * @return {@link SemRelation} representing target - */ - public static SemRelation getRepresentative(final SemAnalysisPanel semArea, final Relation target) { - return semArea.getRelationMap().get(target); - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SingleProjectView.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SingleProjectView.java index 34216ee..aa0e5c7 100644 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SingleProjectView.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SingleProjectView.java @@ -28,8 +28,9 @@ import java.util.Arrays; import java.util.List; import java.util.Map.Entry; - +import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenuItem; +import javax.swing.JToggleButton; import org.hmx.scitos.core.HmxException; import org.hmx.scitos.core.i18n.Message; @@ -62,10 +63,16 @@ public class SingleProjectView extends AbstractProjectView createEditMenuItems() { this.addTextItem = new JMenuItem(HmxMessage.MENUBAR_ORIGINTEXT_ADD.get(), ScitosIcon.ADD.create()); this.addTextItem.addActionListener(new ActionListener() { - @Override public void actionPerformed(final ActionEvent event) { SingleProjectView.this.goToTextInputView(); @@ -285,7 +337,6 @@ public void actionPerformed(final ActionEvent event) { }); this.removeTextItem = new JMenuItem(HmxMessage.MENUBAR_ORIGINTEXT_REMOVE.get(), ScitosIcon.DELETE.create()); this.removeTextItem.addActionListener(new ActionListener() { - @Override public void actionPerformed(final ActionEvent event) { if (SingleProjectView.this.activeView instanceof IPericopeView @@ -303,40 +354,193 @@ public void actionPerformed(final ActionEvent event) { }); this.mergeProjectItem = new JMenuItem(HmxMessage.MENUBAR_PROJECT_MERGE.get(), ScitosIcon.PROJECT_OPEN.create()); this.mergeProjectItem.addActionListener(new ActionListener() { - @Override public void actionPerformed(final ActionEvent event) { SingleProjectView.this.mergeWithOtherPericope(); } }); - final JMenuItem projectInfoItem = new JMenuItem(HmxMessage.MENUBAR_PROJECTINFO.get(), ScitosIcon.CATEGORY.create()); + final JMenuItem projectInfoItem = new JMenuItem(HmxMessage.MENUBAR_PROJECTINFO.get(), ScitosIcon.CLIPBOARD.create()); projectInfoItem.addActionListener(new ActionListener() { - @Override public void actionPerformed(final ActionEvent event) { - final boolean alreadyInProgress = SingleProjectView.this.activeView instanceof CombinedAnalysesPanel; + final boolean alreadyInProgress = SingleProjectView.this.activeView instanceof AnalysisPanel; new ProjectInfoDialog(SingleProjectView.this.getProject(), alreadyInProgress).setVisible(true); } }); + this.manageEditMenuOptions(); return Arrays.asList(this.addTextItem, this.removeTextItem, this.mergeProjectItem, null, projectInfoItem); } @Override public List createViewMenuItems() { - this.toggleLabelsItem = new JMenuItem(HmxMessage.MENUBAR_TOGGLE_PROPOSITION_LABELS.get(), ScitosIcon.ATTRIBUTES_DISPLAY.create()); - this.toggleLabelsItem.addActionListener(new ActionListener() { + this.viewPropositionLabelMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_PROPOSITION_LABELS.get(), + ScitosIcon.ATTRIBUTES_DISPLAY.create()); + this.viewPropositionLabelMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.togglePropositionLabelVisibility(); + } + }); + this.viewPropositionIndentationMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_PROPOSITION_INDENTATIONS.get(), + ScitosIcon.TREE.create()); + this.viewPropositionIndentationMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.togglePropositionIndentationVisibility(); + } + }); + this.viewRelationMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_RELATIONS.get(), + ScitosIcon.RELATIONS.create()); + this.viewRelationMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.toggleRelationVisibility(); + } + }); + this.viewClauseItemMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_CLAUSE_ITEMS.get(), + ScitosIcon.GRID.create()); + this.viewClauseItemMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.toggleClauseItemVisibility(); + } + }); + this.viewSyntacticTranslationMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_SYNTACTIC_TRANSLATIONS.get(), + ScitosIcon.HORIZONTAL_RULE.create()); + this.viewSyntacticTranslationMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.toggleSyntacticTranslationVisibility(); + } + }); + this.viewSemanticTranslationMenuItem = new JCheckBoxMenuItem(HmxMessage.MENUBAR_TOGGLE_SEMANTIC_TRANSLATIONS.get(), + ScitosIcon.HORIZONTAL_RULE.create()); + this.viewSemanticTranslationMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.toggleSemanticTranslationVisibility(); + } + }); + this.manageViewMenuOptions(); + return Arrays.asList(this.viewPropositionLabelMenuItem, this.viewPropositionIndentationMenuItem, this.viewRelationMenuItem, + this.viewClauseItemMenuItem, this.viewSyntacticTranslationMenuItem, this.viewSemanticTranslationMenuItem); + } + + @Override + public List createToolBarItems() { + this.allViewDetailsToolBarItem = new JToggleButton(HmxMessage.ANALYSIS_PRESET_SHOW_ALL.get(), ScitosIcon.ATTRIBUTES_DISPLAY.create()); + this.allViewDetailsToolBarItem.setFocusable(false); + this.allViewDetailsToolBarItem.setName("Preset: All"); + this.allViewDetailsToolBarItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent event) { + SingleProjectView.this.applyViewPreset(IAnalysisViewSettings.SHOW_ALL); + } + }); + this.syntacticalAnalysisToolBarItem = new JToggleButton(HmxMessage.ANALYSIS_PRESET_SYNTACTICAL.get(), ScitosIcon.GRID.create()); + this.syntacticalAnalysisToolBarItem.setFocusable(false); + this.syntacticalAnalysisToolBarItem.setName("Preset: Syntactical"); + this.syntacticalAnalysisToolBarItem.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { - ((CombinedAnalysesPanel) SingleProjectView.this.activeView).togglePropositionLabelVisibility(); + SingleProjectView.this.applyViewPreset(IAnalysisViewSettings.SYNTACTICAL_ANALYSIS); } }); - this.toggleTranslationsItem = new JMenuItem(HmxMessage.MENUBAR_TOGGLE_PROPOSITION_TRANSLATIONS.get(), ScitosIcon.HORIZONTAL_RULE.create()); - this.toggleTranslationsItem.addActionListener(new ActionListener() { + this.semanticalAnalysisToolBarItem = new JToggleButton(HmxMessage.ANALYSIS_PRESET_SEMANTICAL.get(), ScitosIcon.RELATIONS.create()); + this.semanticalAnalysisToolBarItem.setFocusable(false); + this.semanticalAnalysisToolBarItem.setName("Preset: Semantical"); + this.semanticalAnalysisToolBarItem.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { - ((CombinedAnalysesPanel) SingleProjectView.this.activeView).togglePropositionTranslationVisibility(); + SingleProjectView.this.applyViewPreset(IAnalysisViewSettings.SEMANTICAL_ANALYSIS); } }); - return Arrays.asList(this.toggleLabelsItem, this.toggleTranslationsItem); + this.manageToolBarItems(); + return Arrays.asList(this.allViewDetailsToolBarItem, this.syntacticalAnalysisToolBarItem, this.semanticalAnalysisToolBarItem); + } + + /** + * Toggle the visibility of the label fields for all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void togglePropositionLabelVisibility() { + final boolean toggleValue = this.viewSettings.setShowingPropositionLabels(!this.viewSettings.isShowingPropositionLabels()); + this.viewPropositionLabelMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Toggle the visibility of the indentation (and associated functions) of all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void togglePropositionIndentationVisibility() { + final boolean toggleValue = this.viewSettings.setShowingPropositionIndentations(!this.viewSettings.isShowingPropositionIndentations()); + this.viewPropositionIndentationMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Toggle the visibility of the relations over all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void toggleRelationVisibility() { + final boolean toggleValue = this.viewSettings.setShowingRelations(!this.viewSettings.isShowingRelations()); + this.viewRelationMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Toggle between individual clause items and a single origin text field being shown for all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void toggleClauseItemVisibility() { + final boolean toggleValue = this.viewSettings.setShowingClauseItems(!this.viewSettings.isShowingClauseItems()); + this.viewClauseItemMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Toggle the visibility of the syntactic translation fields for all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void toggleSyntacticTranslationVisibility() { + final boolean toggleValue = this.viewSettings.setShowingSyntacticTranslations(!this.viewSettings.isShowingSyntacticTranslations()); + this.viewSyntacticTranslationMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Toggle the visibility of the semantic translation fields for all propositions. Causing a full rebuild of the Pericope. + * + * @see #refresh() + */ + void toggleSemanticTranslationVisibility() { + final boolean toggleValue = this.viewSettings.setShowingSemanticTranslations(!this.viewSettings.isShowingSemanticTranslations()); + this.viewSemanticTranslationMenuItem.setSelected(toggleValue); + this.manageToolBarItems(); + this.refresh(); + } + + /** + * Apply the given view preset (potentially altering multiple individual toggles). Causing a full rebuild of the Pericope. + * + * @param preset collection of view toggles to set + * @see #refresh() + */ + void applyViewPreset(final IAnalysisViewSettings preset) { + this.viewSettings.applyViewPreset(preset); + this.manageViewMenuOptions(); + this.manageToolBarItems(); + this.refresh(); } } diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynAnalysisPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynAnalysisPanel.java deleted file mode 100755 index 2058829..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynAnalysisPanel.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingUtilities; - -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.domain.util.CollectionUtil; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.hmx.view.swing.elements.SynProposition; - -/** - * View displaying the Syntactical Structured Analysis consisting of {@link Proposition}s disregarding super ordinated Relations and semantical - * translations; offering the opportunity to edit the whole syntactical structure displayed. - */ -public final class SynAnalysisPanel extends AbstractAnalysisPanel { - - /** The model change listener responsible for keeping this view up to date while it is active. */ - private final SynControl listener; - /** - * Complete list of all displayed {@link Proposition}s in the correct (i.e. text) order. - */ - private List propositionList = null; - /** The single main view element allowing all its contents to be scrolled. */ - JScrollPane scrollPane = null; - /** - * The actual container of the view components representing {@link Proposition}s. - */ - private final Box contentPane = new Box(BoxLayout.PAGE_AXIS); - - /** - * Constructor. - * - * @param viewReference - * super ordinated view this panel belongs to - */ - public SynAnalysisPanel(final IPericopeView viewReference) { - super(viewReference, new GridLayout(0, 1)); - // collect all possible syntactical Functions - this.listener = new SynControl(this); - this.initView(); - } - - @Override - protected ModelChangeListener getModelChangeListener() { - return this.listener; - } - - /** - * Initialize the general layout and position of the content to display. - */ - private void initView() { - final JPanel scrollable = new JPanel(new GridBagLayout()); - this.contentPane.setBorder(null); - final GridBagConstraints mainConstraints = new GridBagConstraints(); - mainConstraints.anchor = GridBagConstraints.FIRST_LINE_START; - mainConstraints.fill = GridBagConstraints.HORIZONTAL; - mainConstraints.weightx = 1; - scrollable.add(this.contentPane, mainConstraints); - - final GridBagConstraints spacing = new GridBagConstraints(); - spacing.fill = GridBagConstraints.VERTICAL; - spacing.weighty = 1; - spacing.gridy = 1; - scrollable.add(new JPanel(), spacing); - - this.scrollPane = new JScrollPane(scrollable); - this.scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - this.add(this.scrollPane); - } - - @Override - public void deactivate() { - super.deactivate(); - this.propositionList = null; - } - - @Override - public void repaintPericope() { - // remember vertical position - final int verticalPosition = this.scrollPane.getVerticalScrollBar().getValue(); - // clear view - this.getViewReference().submitChangesToModel(); - this.scrollPane.setVisible(false); - this.contentPane.removeAll(); - // get currently used origin text font - this.propositionList = new ArrayList(); - // rebuild proposition list and display propositions - for (final Proposition singleTopLevelProposition : this.getViewReference().getModelHandler().getModel().getText()) { - this.addSynProposition(singleTopLevelProposition, 0); - } - // reset vertical position - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - SynAnalysisPanel.this.scrollPane.setVisible(true); - SynAnalysisPanel.this.scrollPane.getVerticalScrollBar().setValue(verticalPosition); - } - }); - } - - /** - * Add the specified {@link Proposition} and all of its (further indented) child {@link Proposition}s to the view. - * - * @param proposition - * {@link Proposition} to insert in view - * @param level - * indentation level - */ - private void addSynProposition(final Proposition proposition, final int level) { - // first: add all prior children - for (final Proposition singlePriorChild : proposition.getPriorChildren()) { - this.addSynProposition(singlePriorChild, level + 1); - } - // second: add the proposition itself - final SynProposition viewProposition = SynProposition.createSynPropositionByLevel(this.getViewReference(), proposition, level); - this.propositionList.add(viewProposition); - this.contentPane.add(viewProposition); - // third: add all later children - for (final Proposition singleLaterChild : proposition.getLaterChildren()) { - this.addSynProposition(singleLaterChild, level + 1); - } - // finally: add the part after arrow - final Proposition partAfterArrow = proposition.getPartAfterArrow(); - if (partAfterArrow != null) { - this.addSynPropositionAfterArrow(partAfterArrow, level, viewProposition); - } - } - - /** - * Add the specified {@link Proposition} and all of its (further indented) child {@link Proposition}s to the view. - * - * @param proposition - * {@link Proposition} to insert in view - * @param level - * indentation level of the {@code partBeforeArrow} - * @param partBeforeArrow - * view representation of the partBeforeArrow - */ - private void addSynPropositionAfterArrow(final Proposition proposition, final int level, final SynProposition partBeforeArrow) { - // first: add prior children - for (final Proposition singlePriorChild : proposition.getPriorChildren()) { - this.addSynProposition(singlePriorChild, level + 1); - } - // second: add the proposition itself - final SynProposition viewProposition = - SynProposition.createSynPropositionByPartBeforeArrow(this.getViewReference(), proposition, partBeforeArrow); - this.propositionList.add(viewProposition); - // show arrows - final int listSize = this.propositionList.size(); - final int beforeArrowPos = CollectionUtil.indexOfInstance(this.propositionList, partBeforeArrow); - // count number of arrows to set - int arrowCount = listSize - beforeArrowPos - 1; - // ignore partAfterArrows - for (int i = beforeArrowPos + 1; i < listSize; i++) { - if (this.propositionList.get(i).getRepresented().getPartBeforeArrow() != null) { - arrowCount--; - } - } - // show arrows in part before arrow - partBeforeArrow.setRightArrowCount(arrowCount); - // show arrows in target - viewProposition.setLeftArrowCount(arrowCount); - // show proposition in view - this.contentPane.add(viewProposition); - // third: add later children - for (final Proposition singleLaterChild : proposition.getLaterChildren()) { - this.addSynProposition(singleLaterChild, level + 1); - } - // finally: add part after arrow - final Proposition partAfterArrow = proposition.getPartAfterArrow(); - if (partAfterArrow != null) { - this.addSynPropositionAfterArrow(partAfterArrow, level, viewProposition); - } - } - - @Override - public void submitChangesToModel() { - // only the propositions might have any pending changes (e.g. the label and translation fields) - if (this.propositionList != null) { - for (final SynProposition singleProposition : this.propositionList) { - singleProposition.submitChangesToModel(); - } - } - } - - /** - * Collect all checked {@link Proposition}s in the displayed syntactical analysis. - * - * @param clicked - * {@link Proposition} requesting the list, that is included in the result list regardless of it being checked or not (ignored, if it - * is {@code null}) - * @return list of all checked {@link Proposition}s in the correct (i.e. text) order - */ - public List getChecked(final Proposition clicked) { - final List checked = new LinkedList(); - for (final SynProposition singleProposition : this.propositionList) { - if (singleProposition.isChecked() || singleProposition.getRepresented() == clicked) { - checked.add(singleProposition.getRepresented()); - } - } - return checked; - } - - /** - * Getter for the complete list of all displayed {@link Proposition}s in the correct (i.e. text) order. - * - * @return list of all displayed {@link SynProposition}s - */ - public List getPropositionList() { - return Collections.unmodifiableList(this.propositionList); - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynControl.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynControl.java deleted file mode 100755 index 3c89cd1..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/components/SynControl.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.components; - -import java.util.List; - -import javax.swing.SwingUtilities; - -import org.hmx.scitos.domain.ModelChangeListener; -import org.hmx.scitos.domain.ModelEvent; -import org.hmx.scitos.hmx.domain.model.ClauseItem; -import org.hmx.scitos.hmx.domain.model.Pericope; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.view.swing.elements.SynItem; -import org.hmx.scitos.hmx.view.swing.elements.SynProposition; - -/** - * Listener for the {@link SynAnalysisPanel} to react on changed model elements. - */ -public final class SynControl implements ModelChangeListener { - - /** The targeted syntactical analysis view. */ - final SynAnalysisPanel synArea; - - /** - * Constructor. - * - * @param panel - * targeted syntactical analysis view - */ - SynControl(final SynAnalysisPanel panel) { - this.synArea = panel; - } - - /** - * Handle the given {@code event} and update the associated {@link SynAnalysisPanel} accordingly. - * - * @param event - * the {@link ModelEvent} indicating a changed model (part) - */ - @Override - public void modelChanged(final ModelEvent event) { - // deal with different kinds of targets and event types - final Object target = event.getTarget(); - SwingUtilities.invokeLater(new Thread("HmX Syntactical Model Update") { - - @Override - public void run() { - // manage the handling of the event - if (target instanceof Pericope) { - SynControl.this.synArea.repaintPericope(); - } else if (target instanceof Proposition) { - SynControl.this.refreshProposition((Proposition) target); - } else if (target instanceof ClauseItem) { - SynControl.this.refreshClauseItem((ClauseItem) target); - } - // ignore (target instanceof org.hermeneutix.model.Relation) - // target should be no other kind of instance - } - }); - } - - /** - * Handle a {@link ModelEvent} for a single {@link Proposition}. - * - * @param target - * {@link Proposition} to refresh in view - */ - void refreshProposition(final Proposition target) { - final SynProposition representative = SynControl.getRepresentative(this.synArea, target); - if (representative == null) { - // edited proposition currently not displayed - return; - } - if (representative.refreshFunction()) { - // first time function label with an icon is added - this.synArea.repaintPericope(); - return; - } - representative.refreshLabelText(); - representative.refreshTranslation(); - representative.refreshComment(); - // remove all items in view - for (final SynItem singleViewItem : representative.getItems()) { - representative.removeItem(singleViewItem); - } - // reinsert all items in view - for (final ClauseItem singleModelItem : target) { - representative.insertItem(singleModelItem); - } - } - - /** - * Handle a {@link ModelEvent} for a single {@link ClauseItem}. - * - * @param target - * {@link ClauseItem} to refresh in view - */ - void refreshClauseItem(final ClauseItem target) { - final SynItem representative = SynControl.getRepresentative(this.synArea, target); - if (representative != null) { - representative.refreshFontStyle(); - representative.refreshFunction(); - representative.refreshOriginText(); - representative.refreshComment(); - } - } - - /** - * Lookup the view component in the given syntactical analysis view that represent the specified {@link Proposition}. - * - * @param synArea - * syntactical analysis view to find the view component in - * @param target - * {@link Proposition} to look for - * @return {@link SynProposition} representing the {@code target} - */ - public static SynProposition getRepresentative(final SynAnalysisPanel synArea, final Proposition target) { - final List viewPropositions = synArea.getPropositionList(); - for (final SynProposition singleViewProposition : viewPropositions) { - if (target == singleViewProposition.getRepresented()) { - // found representative in the syntactical analysis view - return singleViewProposition; - } - } - // target does not exist in the syntactical analysis view - return null; - } - - /** - * Lookup the view component in the given syntactical analysis view that represent the specified {@link ClauseItem}. - * - * @param synArea - * syntactical analysis view containing the searched representation - * @param target - * {@link ClauseItem} to look for - * @return {@link SynItem} representing the {@code target} - */ - public static SynItem getRepresentative(final SynAnalysisPanel synArea, final ClauseItem target) { - final SynProposition parentRepresentative = SynControl.getRepresentative(synArea, target.getParent()); - if (parentRepresentative != null) { - for (final SynItem singleViewItem : parentRepresentative.getItems()) { - if (target == singleViewItem.getRepresented()) { - return singleViewItem; - } - } - } - // target does not exist in the syntactical analysis view - return null; - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/AbstractProposition.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/AbstractProposition.java deleted file mode 100755 index 6bdcbca..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/AbstractProposition.java +++ /dev/null @@ -1,562 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.elements; - -import java.awt.ComponentOrientation; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.MouseListener; - -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import javax.swing.border.Border; - -import org.hmx.scitos.domain.util.ComparisonUtil; -import org.hmx.scitos.hmx.core.HmxModelHandler; -import org.hmx.scitos.hmx.core.option.HmxGeneralOption; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.view.swing.components.ScaledLabel; -import org.hmx.scitos.view.swing.components.ScaledTextField; -import org.hmx.scitos.view.swing.util.Validation; - -/** - * Abstract mask of the view representation of a {@link Proposition} not specifying how to display the contained origin text
- * offering a uniformed representation of the {@link Proposition}s in the syntactical and semantical analysis views with a {@link JCheckBox}, a - * {@link JTextField} for a short label text, an indentation area, the ability to display arrows in front and behind the origin text area as well as a - * {@link JTextField} for an individual translation text. - */ -abstract class AbstractProposition extends AbstractCommentable implements ICheckable { - - /** raised bevel border, when not selected. */ - private static final Border DEFAULT_BORDER = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), - BorderFactory.createEmptyBorder(2, 2, 6, 2)); - /** lowered bevel border, when selected. */ - private static final Border COMMENT_BORDER = BorderFactory.createCompoundBorder(BorderFactory.createLoweredBevelBorder(), - BorderFactory.createEmptyBorder(2, 2, 6, 2)); - - /** The responsible model handler implementation realizing any model changes. */ - private final HmxModelHandler modelHandler; - /** - * The represented model {@link Proposition}. - */ - private final Proposition represented; - /** raised bevel border with color, when not selected and with comment set. */ - private final Border defaultBorderCommented; - /** The actual container of the components this element is comprised of. This abstraction layer allows it being resized as needed. */ - private final JPanel contentPane = new JPanel(new GridBagLayout()); - /** The input field for the (up to five characters) identifier. */ - private final JTextField labelField; - /** - * The placeholder realizing the indentation of the {@link Proposition} contents. - */ - private final JPanel indentationArea = new JPanel(new GridBagLayout()); - /** - * The placeholder for upward pointing arrows referring to a {@code partBeforeArrow} of the represented {@link Proposition} (part). - */ - private final ArrowStack leftArrows; - /** The container for the origin text, which is displayed differently in the syntactical and semantical analysis. */ - private final JPanel itemArea = new JPanel(); - /** - * The placeholder for downward pointing arrows referring to a {@code partAfterArrow} of the represented {@link Proposition} (part). - */ - private final ArrowStack rightArrows; - /** The input field for the translation text related to the respective analysis (either syntactical or semantical). */ - private final JTextField translationField; - /** - * The view element allowing this {@link Proposition} to be selected for any more complex operations involving multiple model elements. - */ - private final JCheckBox checkBox = new JCheckBox(); - /** - * The view element replacing the {@link #checkBox} if the represented {@link Proposition} is not eligible for being part of any more complex - * operations. - */ - private final JPanel checkBoxDummy = new JPanel(); - - /** - * Constructor: creating an {@link AbstractProposition} by setting all values derived from the represented {@link Proposition}. - * - * @param modelHandler - * the responsible model handler implementation realizing any model changes - * @param represented - * represented {@link Proposition} to set - * @param showLabel - * whether the label field should be shown - * @param showTranslation - * whether the translation field should be shown - */ - protected AbstractProposition(final HmxModelHandler modelHandler, final Proposition represented, final boolean showLabel, - final boolean showTranslation) { - super(new GridBagLayout()); - this.modelHandler = modelHandler; - this.represented = represented; - final boolean leftAligned = modelHandler.getModel().isLeftToRightOriented(); - this.defaultBorderCommented = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), - BorderFactory.createCompoundBorder( - BorderFactory.createMatteBorder(2, leftAligned ? 1 : 0, 2, leftAligned ? 0 : 1, - HmxGeneralOption.COMMENTED_BORDER_COLOR.getValueAsColor()), - BorderFactory.createEmptyBorder(0, leftAligned ? 1 : 2, 4, leftAligned ? 2 : 1))); - final ComponentOrientation orientation = leftAligned ? ComponentOrientation.LEFT_TO_RIGHT : ComponentOrientation.RIGHT_TO_LEFT; - this.setComponentOrientation(orientation); - this.contentPane.setComponentOrientation(orientation); - this.itemArea.setComponentOrientation(orientation); - this.leftArrows = new ArrowStack(true, 0); - this.rightArrows = new ArrowStack(false, 0); - if (showLabel) { - this.labelField = new ScaledTextField(); - } else { - this.labelField = null; - } - this.initCheckboxAndLabel(showLabel); - this.initOriginTextArea(); - if (showTranslation) { - this.translationField = new ScaledTextField(); - this.initTranslationArea(); - } else { - this.translationField = null; - } - this.add(this.contentPane); - this.setDefaultBorder(); - } - - /** - * Initialize the left part of the {@link AbstractProposition} containing the {@link JCheckBox}, the label {@link JTextField} and an expanding - * {@link JPanel} for the indentations in the syntactical analysis view. - * - * @param showLabel - * whether the label field should be shown - */ - private void initCheckboxAndLabel(final boolean showLabel) { - // checkBox - this.checkBoxDummy.setPreferredSize(this.checkBox.getPreferredSize()); - this.setCheckBoxVisible(this.represented.getPartBeforeArrow() == null); - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.gridx = 0; - constraints.gridy = 1; - this.checkBox.setName("Check Box"); - this.contentPane.add(this.checkBox, constraints); - this.contentPane.add(this.checkBoxDummy, constraints); - // labelField - if (showLabel) { - this.labelField.setName("Label Input"); - this.labelField.setColumns(Proposition.MAX_LABEL_LENGTH - 1); - this.labelField.setDocument(new Validation(Proposition.MAX_LABEL_LENGTH)); - this.labelField.addFocusListener(new FocusAdapter() { - - @Override - public void focusLost(final FocusEvent event) { - AbstractProposition.this.submitLabelChanges(); - } - }); - this.refreshLabelText(); - constraints.gridx = 1; - this.contentPane.add(this.labelField, constraints); - } - // indentationArea - constraints.fill = GridBagConstraints.VERTICAL; - constraints.weighty = 1; - constraints.gridheight = 3; - constraints.gridx = 2; - constraints.gridy = 0; - this.contentPane.add(this.indentationArea, constraints); - } - - /** - * Ensure that any pending changes (e.g. in the label or translation field) are being submitted to the model handler. - */ - public void submitChangesToModel() { - if (this.labelField != null) { - this.submitLabelChanges(); - } - if (this.translationField != null) { - this.submitTranslationChanges(); - } - } - - /** - * Ensure that any changes in the label field are submitted to the model. - */ - final void submitLabelChanges() { - // only transfer if necessary - final String labelText = this.labelField.getText(); - if (!ComparisonUtil.isNullOrEmptyAwareEqual(this.represented.getLabel(), labelText)) { - this.getModelHandler().setLabelText(this.represented, labelText); - } - } - - /** - * Ensure that any changes in the translation field are submitted to the model. - */ - protected abstract void submitTranslationChanges(); - - /** - * Getter for the associated {@link HmxModelHandler} implementation. - * - * @return the responsible model handler implementation realizing any model changes - */ - protected final HmxModelHandler getModelHandler() { - return this.modelHandler; - } - - /** - * Initialize the top right part of the {@link Proposition} containing a panel for the origin text as well as arrows on the left and on the right - * side of it. - */ - private void initOriginTextArea() { - // leftArrows - final GridBagConstraints arrowConstraints = new GridBagConstraints(); - arrowConstraints.anchor = GridBagConstraints.CENTER; - arrowConstraints.gridx = 3; - arrowConstraints.gridy = 0; - arrowConstraints.gridheight = 2; - this.contentPane.add(this.leftArrows, arrowConstraints); - // itemArea - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.gridx = 4; - constraints.gridy = 0; - constraints.gridheight = 2; - this.contentPane.add(this.itemArea, constraints); - // rightArrows - arrowConstraints.gridx = 5; - this.contentPane.add(this.rightArrows, arrowConstraints); - // just to make sure rightArrows are behind the itemArea in case of an - // expanded translation field - final GridBagConstraints rightSpacing = new GridBagConstraints(); - rightSpacing.fill = GridBagConstraints.HORIZONTAL; - rightSpacing.weightx = 1; - rightSpacing.gridx = 6; - rightSpacing.gridy = 0; - rightSpacing.gridheight = 2; - this.contentPane.add(new JPanel(), rightSpacing); - } - - /** - * Initialize the bottom right part of the {@link Proposition} containing the text field for the translation. - */ - private void initTranslationArea() { - this.translationField.setName("Translation Input"); - this.translationField.setDocument(new Validation(Proposition.MAX_TRANSLATION_LENGTH)); - this.refreshTranslation(); - this.translationField.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(final FocusEvent event) { - AbstractProposition.this.submitTranslationChanges(); - } - }); - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.weighty = 1; - constraints.gridwidth = 4; - constraints.gridx = 3; - constraints.gridy = 2; - this.contentPane.add(this.translationField, constraints); - } - - /** - * Getter for the identifier's input field. - * - * @return label field (can be {@code null}) - */ - protected final JTextField getLabelField() { - return this.labelField; - } - - /** - * Getter for the placeholder realizing the indentation of the {@link Proposition} contents. - * - * @return indentation area - */ - protected final JPanel getIndentationArea() { - return this.indentationArea; - } - - /** - * Getter for the placeholder for upward pointing arrows referring to a {@code partBeforeArrow} of the represented {@link Proposition} (part). - * - * @return left arrow stack - */ - protected final ArrowStack getLeftArrows() { - return this.leftArrows; - } - - /** - * Setter for the number of displayed upward arrows on the left of the item area. - * - * @param count - * number of displayed arrows to set - */ - public final void setLeftArrowCount(final int count) { - this.leftArrows.setArrowCount(count); - } - - /** - * Getter for the origin text container, which is displayed differently in the syntactical and semantical analysis. - * - * @return item area containing the origin text - */ - protected final JPanel getItemArea() { - return this.itemArea; - } - - /** - * Getter for the placeholder for downward pointing arrows referring to a {@code partAfterArrow} of the represented {@link Proposition} (part). - * - * @return right arrow stack - */ - protected final ArrowStack getRightArrows() { - return this.rightArrows; - } - - /** - * Setter for the number of displayed downward arrows on the right of the item area. - * - * @param count - * number of displayed arrows to set - */ - public final void setRightArrowCount(final int count) { - this.rightArrows.setArrowCount(count); - } - - /** - * Getter for the translation input field. - * - * @return translation field (can be {@code null}) - */ - protected final JTextField getTranslationField() { - return this.translationField; - } - - /** - * Getter for the represented {@link Proposition}. - * - * @return represented model element - */ - @Override - public final Proposition getRepresented() { - return this.represented; - } - - /** - * Update the displayed identifier text to match the value in the represented {@link Proposition}. - */ - public final void refreshLabelText() { - if (this.labelField != null) { - this.labelField.setText(this.represented.getLabel()); - } - } - - /** - * This does NOT refresh the translation TEXT, just fits the {@link Proposition} to the possible expanded translation field size. RECOMMENDED: - * Override and use this method in extending class to refresh and fit the changed translation text. - */ - protected void refreshTranslation() { - if (this.translationField != null) { - // if the translation text wants more space, it gets more - final Dimension preferred = this.translationField.getPreferredSize(); - final int itemAreaWidth = this.itemArea.getSize().width; - if (preferred.width > itemAreaWidth) { - // enlarge the translation field - this.translationField.setSize(preferred); - } else { - this.translationField.setSize(new Dimension(itemAreaWidth, preferred.height)); - } - // enlarge the containing proposition - this.contentPane.setSize(this.contentPane.getPreferredSize()); - // make sure it is still displayed - this.itemArea.validate(); - } - } - - /** - * resets the tool tip info containing the comment text regarding its value in the represented {@link Proposition}. - */ - public void refreshComment() { - final String comment = this.getRepresented().getComment(); - if (comment == null || comment.isEmpty()) { - this.setToolTipText(null); - } else { - this.setToolTipText(comment); - } - } - - @Override - public final boolean isChecked() { - return this.checkBox.isSelected(); - } - - @Override - public final void setNotChecked() { - this.checkBox.setSelected(false); - } - - /** - * Setter for the contained checkbox's visibility. - * - * @param visible - * visibility to set - */ - public final void setCheckBoxVisible(final boolean visible) { - this.checkBox.setVisible(visible); - this.checkBoxDummy.setVisible(!visible); - } - - /** - * creates a {@link Dimension} for the indentation by setting its width regarding to the specified level. - * - * @param level - * number of indentations to be contained - * @return {@link Dimension} representing the indentation - */ - protected static final Dimension createIndentation(final int level) { - return new Dimension(HmxGeneralOption.INDENTATION_WIDTH.getValueAsInteger() * level, 1); - } - - @Override - public void setDefaultBorder() { - final boolean containsComment = this.represented.getComment() != null && !this.represented.getComment().trim().isEmpty(); - this.contentPane.setBorder(containsComment ? this.defaultBorderCommented : AbstractProposition.DEFAULT_BORDER); - // without these visibility changes the item area may disappear - this.itemArea.setVisible(false); - // make sure the item area is still visible - this.itemArea.setVisible(true); - } - - @Override - public final void setCommentBorder() { - this.contentPane.setBorder(AbstractProposition.COMMENT_BORDER); - // without these visibility changes the item area may disappear - this.itemArea.setVisible(false); - // make sure the item area is still visible - this.itemArea.setVisible(true); - } - - /** - * Add the specified {@link MouseListener} to all components included except the single {@link SynItem}s in the syntactical analysis view. - */ - @Override - public synchronized void addMouseListener(final MouseListener listener) { - super.addMouseListener(listener); - if (this.labelField != null) { - this.labelField.addMouseListener(listener); - } - this.indentationArea.addMouseListener(listener); - this.leftArrows.addMouseListener(listener); - this.itemArea.addMouseListener(listener); - this.rightArrows.addMouseListener(listener); - if (this.translationField != null) { - this.translationField.addMouseListener(listener); - } - } - - /** - * Ses the specified tool tip text to all of its components except the single {@link SynItem}s in the syntactical analysis view. - */ - @Override - public synchronized void setToolTipText(final String toolTip) { - super.setToolTipText(toolTip); - if (this.labelField != null) { - this.labelField.setToolTipText(toolTip); - } - this.indentationArea.setToolTipText(toolTip); - this.leftArrows.setToolTipText(toolTip); - this.itemArea.setToolTipText(toolTip); - this.rightArrows.setToolTipText(toolTip); - if (this.translationField != null) { - this.translationField.setToolTipText(toolTip); - } - } - - /** - * A stack of arrows pointing up or down to indicate the connection of two {@link Proposition} parts with enclosed children. - */ - protected static final class ArrowStack extends ScaledLabel { - - /** The base font size to apply – will be scaled with global setting. */ - private static final int BASE_ARROW_FONT_SIZE = 20; - - /** If the displayed arrows are pointing from bottom to top; else top to bottom. */ - private final boolean upward; - /** The current number of arrows being displayed. */ - private int arrowCount = 0; - - /** - * Constructor. - * - * @param pointsUp - * flag if the arrows should point upwards - * @param count - * number of arrows to display - */ - ArrowStack(final boolean pointsUp, final int count) { - super(ArrowStack.buildArrowString(pointsUp, count), SwingConstants.CENTER); - this.upward = pointsUp; - this.setFont(new Font("Times New Roman", Font.BOLD, ArrowStack.BASE_ARROW_FONT_SIZE)); - this.setForeground(HmxGeneralOption.ARROW_COLOR.getValueAsColor()); - this.setArrowCount(count); - } - - /** - * Setter for the number of displayed arrows. - * - * @param count - * number of displayed arrows to set - */ - void setArrowCount(final int count) { - if (this.arrowCount != count) { - this.arrowCount = count; - if (count == 0) { - this.setVisible(false); - this.setText(""); - } else { - this.setText(ArrowStack.buildArrowString(this.upward, count)); - this.setSize(this.getPreferredSize()); - this.setVisible(true); - } - } - } - - /** - * Construct a string with the given number of arrows pointing in the indicating direction. - * - * @param pointsUp - * if the arrows should point upwards, otherwise downwards - * @param arrowCount - * number arrows to include - * @return string of unicode arrows - */ - private static String buildArrowString(final boolean pointsUp, final int arrowCount) { - if (arrowCount < 1) { - return ""; - } - final char singleArrow = pointsUp ? '\u2191' : '\u2193'; - final StringBuffer arrows = new StringBuffer(arrowCount); - for (int i = 0; i < arrowCount; i++) { - arrows.append(singleArrow); - } - return arrows.toString(); - } - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ArrowStackLabel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ArrowStackLabel.java new file mode 100644 index 0000000..c9823fe --- /dev/null +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ArrowStackLabel.java @@ -0,0 +1,91 @@ +/* + Copyright (C) 2017 HermeneutiX.org + + This file is part of SciToS. + + SciToS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SciToS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SciToS. If not, see . + */ + +package org.hmx.scitos.hmx.view.swing.elements; + +import java.awt.Font; +import javax.swing.SwingConstants; +import org.hmx.scitos.hmx.core.option.HmxGeneralOption; +import org.hmx.scitos.view.swing.components.ScaledLabel; + +/** + * A stack of arrows pointing up or down to indicate the connection of two {@link Proposition} parts with enclosed children. + */ +final class ArrowStackLabel extends ScaledLabel { + + /** The base font size to apply – will be scaled with global setting. */ + private static final int BASE_ARROW_FONT_SIZE = 20; + + /** If the displayed arrows are pointing from bottom to top; else top to bottom. */ + private final boolean upward; + /** The current number of arrows being displayed. */ + private int arrowCount = 0; + + /** + * Constructor. + * + * @param pointsUp flag if the arrows should point upwards + * @param count number of arrows to display + */ + ArrowStackLabel(final boolean pointsUp, final int count) { + super(ArrowStackLabel.buildArrowString(pointsUp, count), SwingConstants.CENTER); + this.upward = pointsUp; + this.setFont(new Font("Times New Roman", Font.BOLD, ArrowStackLabel.BASE_ARROW_FONT_SIZE)); + this.setForeground(HmxGeneralOption.ARROW_COLOR.getValueAsColor()); + this.setArrowCount(count); + } + + /** + * Setter for the number of displayed arrows. + * + * @param count number of displayed arrows to set + */ + void setArrowCount(final int count) { + if (this.arrowCount != count) { + this.arrowCount = count; + if (count < 1) { + this.setVisible(false); + this.setText(""); + } else { + this.setText(ArrowStackLabel.buildArrowString(this.upward, count)); + this.setSize(this.getPreferredSize()); + this.setVisible(true); + } + } + } + + /** + * Construct a string with the given number of arrows pointing in the indicating direction. + * + * @param pointsUp if the arrows should point upwards, otherwise downwards + * @param arrowCount number arrows to include + * @return string of unicode arrows + */ + private static String buildArrowString(final boolean pointsUp, final int arrowCount) { + if (arrowCount < 1) { + return ""; + } + final char singleArrow = pointsUp ? '\u2191' : '\u2193'; + final StringBuffer arrows = new StringBuffer(arrowCount); + for (int i = 0; i < arrowCount; i++) { + arrows.append(singleArrow); + } + return arrows.toString(); + } +} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/IConnectable.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/IConnectable.java index d56c952..71fa7e3 100755 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/IConnectable.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/IConnectable.java @@ -39,14 +39,6 @@ public interface IConnectable extends ICheckable */ T getRepresented(); - /** - * Toggle the integrated check box's visibility on/off. - * - * @param visible - * if the check box should be visible - */ - void setCheckBoxVisible(final boolean visible); - /** * Getter for the number of {@link Relation} levels between the represented model element and the underlying {@link Proposition}s. If the * represented model element is a {@link Proposition}, this returns {@code 0}. diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemProposition.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemProposition.java deleted file mode 100755 index 0082a92..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemProposition.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.elements; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.BorderFactory; -import javax.swing.JTextField; - -import org.hmx.scitos.domain.util.CollectionUtil; -import org.hmx.scitos.domain.util.ComparisonUtil; -import org.hmx.scitos.hmx.domain.model.ClauseItem; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.view.ContextMenuFactory; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.hmx.view.swing.components.SemAnalysisPanel; -import org.hmx.scitos.view.ContextMenuBuilder; -import org.hmx.scitos.view.swing.ContextMenuPopupBuilder; -import org.hmx.scitos.view.swing.components.ScaledTextField; - -/** - * extension of the {@link AbstractProposition} with a non-editable {@link JTextField} for the origin text in the top right position. - */ -public final class SemProposition extends AbstractProposition implements IConnectable { - - /** The super ordinated semantical analysis this is a part of. */ - private final SemAnalysisPanel semArea; - /** - * The single text field displaying the origin text of all {@link ClauseItem}s of the represented {@link Proposition}. - */ - private final JTextField originText = new ScaledTextField(); - - /** - * Constructor: for an element on the specified {@link SemAnalysisPanel} representing the designated {@link Proposition}. - * - * @param viewReference - * the view providing access to the project's model handler and handling the comments on model elements - * @param semPanel - * semantical analysis to be contained in - * @param represented - * model {@link Proposition} to represent/display - */ - public SemProposition(final IPericopeView viewReference, final SemAnalysisPanel semPanel, final Proposition represented) { - super(viewReference.getModelHandler(), represented, viewReference.isShowingPropositionLabels(), - viewReference.isShowingPropositionTranslations()); - this.semArea = semPanel; - - this.originText.setFont(this.getModelHandler().getModel().getFont()); - this.originText.setEditable(false); - this.originText.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), - BorderFactory.createEmptyBorder(2, 5, 2, 5))); - this.refreshOriginText(); - this.getItemArea().add(this.originText); - this.refreshComment(); - - // indent partAfterArrow - if (represented.getPartBeforeArrow() != null) { - this.getIndentationArea().setPreferredSize(AbstractProposition.createIndentation(1)); - } - this.setCheckBoxVisible(represented.getSuperOrdinatedRelation() == null); - this.addMouseListener(new MouseAdapter() { - - @Override - public void mousePressed(final MouseEvent event) { - viewReference.handleSelectedCommentable(SemProposition.this); - this.mouseReleased(event); - } - - @Override - public void mouseReleased(final MouseEvent event) { - if (event.isPopupTrigger()) { - final ContextMenuBuilder contextMenu = ContextMenuFactory.createSemPropositionPopup(viewReference, represented); - ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); - } - } - }); - } - - @Override - protected void submitTranslationChanges() { - final String translationText = this.getTranslationField().getText(); - // only transfer if necessary - if (!ComparisonUtil.isNullOrEmptyAwareEqual(translationText, this.getRepresented().getSemTranslation())) { - this.getModelHandler().setSemTranslation(this.getRepresented(), translationText); - } - } - - @Override - public int getDepth() { - // propositions are always on the lowest level - return 0; - } - - /** - * Getter for the represented {@link Proposition}'s origin text. - * - * @return displayed origin text - */ - public String getOriginText() { - return this.originText.getText(); - } - - /** - * Set the displayed origin text regarding to the origin text stored in the represented {@link Proposition}'s {@link ClauseItem}s. - */ - public void refreshOriginText() { - final StringBuffer text = new StringBuffer(" "); - for (final ClauseItem singleItem : this.getRepresented()) { - text.append(singleItem.getOriginText()).append(' '); - } - this.originText.setText(text.toString()); - this.originText.setSize(this.originText.getPreferredSize()); - } - - @Override - public double getConnectY() { - return 0.5 + CollectionUtil.indexOfInstance(this.semArea.getPropositionList(), this); - } - - /** - * sets the semantical translation text regarding the stored translation in the represented {@link Proposition}. - * - * @see AbstractProposition#refreshTranslation() - */ - @Override - public void refreshTranslation() { - if (this.getTranslationField() != null) { - this.getTranslationField().setText(this.getRepresented().getSemTranslation()); - } - super.refreshTranslation(); - } - - @Override - public synchronized void addMouseListener(final MouseListener listener) { - this.originText.addMouseListener(listener); - super.addMouseListener(listener); - } - - @Override - public synchronized void setToolTipText(final String toolTip) { - this.originText.setToolTipText(toolTip); - super.setToolTipText(toolTip); - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynProposition.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynProposition.java deleted file mode 100755 index 7e12e71..0000000 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynProposition.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - Copyright (C) 2016 HermeneutiX.org - - This file is part of SciToS. - - SciToS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - SciToS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with SciToS. If not, see . - */ - -package org.hmx.scitos.hmx.view.swing.elements; - -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import javax.swing.JLabel; -import javax.swing.JPanel; - -import org.hmx.scitos.domain.util.ComparisonUtil; -import org.hmx.scitos.hmx.domain.model.ClauseItem; -import org.hmx.scitos.hmx.domain.model.Proposition; -import org.hmx.scitos.hmx.domain.model.SyntacticalFunction; -import org.hmx.scitos.hmx.view.ContextMenuFactory; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.view.ContextMenuBuilder; -import org.hmx.scitos.view.swing.ContextMenuPopupBuilder; -import org.hmx.scitos.view.swing.components.ScaledLabel; -import org.hmx.scitos.view.swing.util.VTextIcon; - -/** - * Extension of the {@link AbstractProposition} with a {@link SynItem}s in the top right area to display the contained {@link ClauseItem}s and their - * included origin text. - */ -public final class SynProposition extends AbstractProposition { - - /** Containing view, providing access to higher functions. */ - final IPericopeView viewReference; - /** label displaying the syntactical indentation function. */ - private final JLabel functionLabel = new ScaledLabel(" "); - /** view representation of the contained clause items. */ - private final List items = new LinkedList(); - - /** - * Constructor. - * - * @param viewReference - * the containing view, providing access to higher functions - * @param represented - * represented {@link Proposition} to set - */ - private SynProposition(final IPericopeView viewReference, final Proposition represented) { - super(viewReference.getModelHandler(), represented, viewReference.isShowingPropositionLabels(), - viewReference.isShowingPropositionTranslations()); - this.viewReference = viewReference; - this.init(); - this.addMouseListener(new MouseAdapter() { - - @Override - public void mousePressed(final MouseEvent event) { - viewReference.handleSelectedCommentable(SynProposition.this); - this.mouseReleased(event); - } - - @Override - public void mouseReleased(final MouseEvent event) { - if (event.isPopupTrigger()) { - final ContextMenuBuilder contextMenu; - if (SynProposition.this.getRepresented().getPartBeforeArrow() == null) { - contextMenu = ContextMenuFactory.createSynPropositionPopup(viewReference, represented); - } else { - contextMenu = ContextMenuFactory.createSynPropositionAfterArrowPopup(viewReference, represented); - } - ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); - } - } - }); - } - - /** - * Create a {@link SynProposition} representing the given {@link Proposition} on the specified indentation {@code level}. - * - * @param viewReference - * the containing view, providing access to higher functions - * @param represented - * represented {@link Proposition} to set - * @param level - * number of indentations to set - * @return created {@link SynProposition} - */ - public static SynProposition createSynPropositionByLevel(final IPericopeView viewReference, final Proposition represented, final int level) { - final SynProposition created = new SynProposition(viewReference, represented); - if (level > 0) { - created.getIndentationArea().setPreferredSize(AbstractProposition.createIndentation(level)); - } - return created; - } - - /** - * Create a {@link SynProposition} representing the given {@link Proposition}, which is the {@code partAfterArrow} for the other given - * {@link SynProposition}, determining the created elements indentation. - * - * @param viewReference - * the containing view, providing access to higher functions - * @param represented - * represented {@link Proposition} part to set - * @param partBeforeArrow - * view representation of the {@code partBeforeArrow} - * @return created {@link SynProposition} - */ - public static SynProposition createSynPropositionByPartBeforeArrow(final IPericopeView viewReference, final Proposition represented, - final SynProposition partBeforeArrow) { - final SynProposition created = new SynProposition(viewReference, represented); - created.getIndentationArea().setPreferredSize(SynProposition.createIndentationAfterArrow(partBeforeArrow)); - return created; - } - - /** - * Create a {@link Dimension} for the indentation by settings its width regarding to the width of the view representation of the - * {@code partBeforeArrow}. - * - * @param partBeforeArrow - * view representation of the {@code partBeforeArrow} - * @return {@link Dimension} representing the indentation - */ - private static Dimension createIndentationAfterArrow(final SynProposition partBeforeArrow) { - return new Dimension(partBeforeArrow.getIndentationArea().getPreferredSize().width - + partBeforeArrow.getLeftArrows().getPreferredSize().width + partBeforeArrow.getItemArea().getPreferredSize().width, 1); - } - - /** - * Initialize the {@link JLabel} in the indentation area for displaying its indentation function and an expanding {@link JPanel} on the right to - * make sure it is always at the left side of its parent and the explicit syntactical functionality by inserting the contained {@link SynItem}s, - * adding a listener to the translation field and activating the comment listener. - */ - private void init() { - final SyntacticalFunction function = this.getRepresented().getFunction(); - if (this.getRepresented().getParent() instanceof Proposition && function != null) { - this.refreshFunction(); - final GridBagConstraints spacing = new GridBagConstraints(); - spacing.fill = GridBagConstraints.HORIZONTAL; - spacing.weightx = 1; - this.getIndentationArea().add(new JPanel(), spacing); - final int border = (AbstractProposition.createIndentation(1).width - this.functionLabel.getPreferredSize().width) / 2; - final GridBagConstraints verticalSpan = new GridBagConstraints(); - verticalSpan.fill = GridBagConstraints.VERTICAL; - verticalSpan.weighty = 1; - verticalSpan.insets = new Insets(0, border, 0, border); - this.getIndentationArea().add(this.functionLabel, verticalSpan); - } - // create expanding panel on the right side of the proposition - final GridBagConstraints rightSpacing = new GridBagConstraints(); - rightSpacing.fill = GridBagConstraints.HORIZONTAL; - rightSpacing.weightx = 1; - rightSpacing.gridx = 1; - rightSpacing.gridy = 0; - this.add(new JPanel(), rightSpacing); - for (final ClauseItem singleItem : this.getRepresented()) { - this.insertItem(singleItem); - } - this.refreshComment(); - } - - @Override - protected void submitTranslationChanges() { - final String translationText = this.getTranslationField().getText(); - // only transfer if necessary - if (!ComparisonUtil.isNullOrEmptyAwareEqual(translationText, this.getRepresented().getSynTranslation())) { - this.getModelHandler().setSynTranslation(this.getRepresented(), translationText); - } - } - - /** - * Insert the specified {@link ClauseItem} at the end of the displayed {@link SynItem}s. - * - * @param item - * {@link ClauseItem} to insert - */ - public void insertItem(final ClauseItem item) { - final SynItem singleItem = new SynItem(this.viewReference, item); - this.items.add(singleItem); - this.getItemArea().add(singleItem); - } - - /** - * Remove the specified {@link SynItem} from the displayed item area. - * - * @param target - * {@link SynItem} to remove - */ - public void removeItem(final SynItem target) { - target.setVisible(false); - this.items.remove(target); - this.getItemArea().remove(target); - } - - /** - * Getter for the contained {@link SynItem}s. - * - * @return displayed {@link SynItem}s - */ - public List getItems() { - return new ArrayList(this.items); - } - - /** - * Update the indentation function (in relation to the parent {@link Proposition}) to match the represented {@link Proposition}'s function value. - * - * @return if a {@code repaint()} is neccessary - */ - public boolean refreshFunction() { - final SyntacticalFunction function = this.getRepresented().getFunction(); - if (!(this.getRepresented().getParent() instanceof Proposition) || function == null) { - return false; - } - if (this.functionLabel.getIcon() == null) { - this.functionLabel.setIcon(new VTextIcon(this.functionLabel, function.getCode(), VTextIcon.Rotate.NONE)); - } else { - ((VTextIcon) this.functionLabel.getIcon()).setLabel(function.getCode()); - } - return true; - } - - /** - * Update the syntactical translation text to match the stored translation in the represented {@link Proposition}. - * - * @see AbstractProposition#refreshTranslation() - */ - @Override - public void refreshTranslation() { - if (this.getTranslationField() != null) { - this.getTranslationField().setText(this.getRepresented().getSynTranslation()); - } - super.refreshTranslation(); - } - - @Override - public void setDefaultBorder() { - super.setDefaultBorder(); - if (this.items != null) { - this.getItemArea().revalidate(); - for (final SynItem singleItem : this.getItems()) { - singleItem.revalidate(); - } - } - } -} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynItem.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewClauseItem.java similarity index 85% rename from scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynItem.java rename to scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewClauseItem.java index 1674141..94f2232 100755 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SynItem.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewClauseItem.java @@ -52,7 +52,7 @@ * view representation of a {@link ClauseItem} in the syntactical analysis view consisting of a non-editable {@link JTextPane} for the origin text on * the top and a label displaying the current selected function on the bottom. */ -public final class SynItem extends AbstractCommentable { +public final class ViewClauseItem extends AbstractCommentable { /** etched border, when not selected. */ private static final Border DEFAULT_BORDER = BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), @@ -86,7 +86,7 @@ public final class SynItem extends AbstractCommentable { * @param represented * model element to represent/display */ - protected SynItem(final IPericopeView viewReference, final ClauseItem represented) { + protected ViewClauseItem(final IPericopeView viewReference, final ClauseItem represented) { super(new GridBagLayout()); this.viewReference = viewReference; this.represented = represented; @@ -95,18 +95,29 @@ protected SynItem(final IPericopeView viewReference, final ClauseItem represente this.setDefaultBorder(); this.initOriginTextPane(); this.initFunctionLabel(); - this.refreshFontStyle(); - // initialize the comment showing listener for the item + this.refresh(); this.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent event) { - viewReference.handleSelectedCommentable(SynItem.this); + viewReference.handleSelectedCommentable(ViewClauseItem.this); + this.mouseReleased(event); + } + + @Override + public void mouseReleased(final MouseEvent event) { + if (event.isPopupTrigger()) { + final ClauseItem item = ViewClauseItem.this.getRepresented(); + final ContextMenuBuilder contextMenu; + if (item.getParent().getPartBeforeArrow() == null) { + contextMenu = ContextMenuFactory.createClauseItemPopup(ViewClauseItem.this.viewReference, item); + } else { + contextMenu = ContextMenuFactory.createClauseItemAfterArrowPopup(ViewClauseItem.this.viewReference, item); + } + ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); + } } }); - // initialize the popup menu and its listener for the item - this.refreshPopup(); - this.refreshComment(); } /** Initialize the origin text pane on the top. */ @@ -136,49 +147,25 @@ private void initFunctionLabel() { this.add(this.functionLabel, constraints); } - /** - * Create and enable the {@link JPopupMenu}. - */ - private void refreshPopup() { - if (this.popupListener != null) { - // remove the old popup listener - this.removeMouseListener(this.popupListener); - } - // create new popup menu and its referring listener - this.popupListener = new MouseAdapter() { - - @Override - public void mousePressed(final MouseEvent event) { - if (event.isPopupTrigger()) { - final ClauseItem item = SynItem.this.getRepresented(); - final ContextMenuBuilder contextMenu; - if (item.getParent().getPartBeforeArrow() == null) { - contextMenu = ContextMenuFactory.createSynItemPopup(SynItem.this.viewReference, item); - } else { - contextMenu = ContextMenuFactory.createSynItemAfterArrowPopup(SynItem.this.viewReference, item); - } - ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); - } - } - - @Override - public void mouseReleased(final MouseEvent event) { - this.mousePressed(event); - } - }; - // add the popup menu and its listener - this.addMouseListener(this.popupListener); - } - @Override public ClauseItem getRepresented() { return this.represented; } + /** + * Update the displayed data and style according to the (potentially changed) state of the represented {@link ClauseItem}. + */ + public void refresh() { + this.refreshFontStyle(); + this.refreshOriginText(); + this.refreshFunction(); + this.refreshComment(); + } + /** * Update the displayed {@link SyntacticalFunction} to match the current value in the represented {@link ClauseItem}. */ - public void refreshFunction() { + void refreshFunction() { final SyntacticalFunction function = this.represented.getFunction(); final String functionName; final boolean underline; @@ -190,31 +177,30 @@ public void refreshFunction() { underline = function.isUnderlined(); } this.functionLabel.setText(functionName); - SynItem.setTextPaneUnderlined(this.originTextPane, underline); + ViewClauseItem.setTextPaneUnderlined(this.originTextPane, underline); this.functionLabel.setSize(this.functionLabel.getPreferredSize()); } /** * Update the displayed origin text to match the current value in the represented {@link ClauseItem}. */ - public void refreshOriginText() { + void refreshOriginText() { this.originTextPane.setText(this.represented.getOriginText()); - this.refreshPopup(); } /** * Update the displayed {@link Font} style to match the current setting in the represented {@link ClauseItem}. */ - public void refreshFontStyle() { + void refreshFontStyle() { final Style style = this.represented.getFontStyle(); - SynItem.setTextPaneFontStyle(this.originTextPane, style); + ViewClauseItem.setTextPaneFontStyle(this.originTextPane, style); this.functionLabel.setFont(this.functionLabel.getFont().deriveFont(ContextMenuFactory.getFontStyleValue(style))); } /** * Reset the tool tip info containing the comment text to match the value in the represented {@link ClauseItem}. */ - public void refreshComment() { + void refreshComment() { final String comment = this.getRepresented().getComment(); if (comment == null || comment.isEmpty()) { this.setToolTipText(null); @@ -226,15 +212,15 @@ public void refreshComment() { @Override public void setDefaultBorder() { final boolean containsComment = this.represented.getComment() != null && !this.represented.getComment().trim().isEmpty(); - this.setBorder(containsComment ? this.defaultBorderCommented : SynItem.DEFAULT_BORDER); + this.setBorder(containsComment ? this.defaultBorderCommented : ViewClauseItem.DEFAULT_BORDER); if (this.getParent() != null) { - ((JComponent) this.getParent()).revalidate(); + this.getParent().revalidate(); } } @Override public void setCommentBorder() { - this.setBorder(SynItem.COMMENT_BORDER); + this.setBorder(ViewClauseItem.COMMENT_BORDER); } @Override diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewProposition.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewProposition.java new file mode 100644 index 0000000..2098344 --- /dev/null +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewProposition.java @@ -0,0 +1,749 @@ +/* + Copyright (C) 2017 HermeneutiX.org + + This file is part of SciToS. + + SciToS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SciToS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SciToS. If not, see . + */ + +package org.hmx.scitos.hmx.view.swing.elements; + +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.Border; + +import org.hmx.scitos.domain.util.ComparisonUtil; +import org.hmx.scitos.hmx.core.option.HmxGeneralOption; +import org.hmx.scitos.hmx.domain.model.ClauseItem; +import org.hmx.scitos.hmx.domain.model.Proposition; +import org.hmx.scitos.hmx.domain.model.SyntacticalFunction; +import org.hmx.scitos.hmx.view.ContextMenuFactory; +import org.hmx.scitos.hmx.view.IPericopeView; +import org.hmx.scitos.hmx.view.swing.components.IAnalysisViewSettings; +import org.hmx.scitos.view.ContextMenuBuilder; +import org.hmx.scitos.view.swing.ContextMenuPopupBuilder; +import org.hmx.scitos.view.swing.components.ScaledLabel; +import org.hmx.scitos.view.swing.components.ScaledTextField; +import org.hmx.scitos.view.swing.util.VTextIcon; +import org.hmx.scitos.view.swing.util.Validation; + +/** + * AView representation of a {@link Proposition} with a check box, an input for a short label text, an indentation area, the ability to display arrows + * in front and behind the origin text area as well as inputs for individual translation texts. + */ +public final class ViewProposition extends AbstractCommentable implements IConnectable { + + /** raised bevel border, when not selected. */ + private static final Border DEFAULT_BORDER = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), + BorderFactory.createEmptyBorder(2, 2, 6, 2)); + /** lowered bevel border, when selected. */ + private static final Border COMMENT_BORDER = BorderFactory.createCompoundBorder(BorderFactory.createLoweredBevelBorder(), + BorderFactory.createEmptyBorder(2, 2, 6, 2)); + + /** Containing view, providing access to higher functions. */ + final IPericopeView viewReference; + /** + * The represented model {@link Proposition}. + */ + private final Proposition represented; + /** + * Index of the represented {@link Proposition} in the pericope. + */ + private final int propositionIndex; + /** raised bevel border with color, when not selected and with comment set. */ + private final Border defaultBorderCommented; + /** The actual container of the components this element is comprised of. This abstraction layer allows it being resized as needed. */ + private final JPanel contentPane = new JPanel(new GridBagLayout()); + /** The input field for the (up to five characters) identifier. */ + private final ScaledTextField labelField; + /** + * The placeholder realizing the indentation of the {@link Proposition} contents. + */ + private final JPanel indentationArea; + /** label displaying the syntactical indentation function. */ + private final JLabel functionLabel; + /** + * The placeholder for upward pointing arrows referring to a {@code partBeforeArrow} of the represented {@link Proposition} (part). + */ + private final ArrowStackLabel leftArrows; + /** The container for the origin text. */ + private final JPanel itemArea = new JPanel(); + /** + * The single text field displaying the concatenated origin text of all {@link ClauseItem}s of the represented {@link Proposition}. + */ + private final JTextField originText; + /** View representation of the contained clause items. */ + private final List items; + /** + * The placeholder for downward pointing arrows referring to a {@code partAfterArrow} of the represented {@link Proposition} (part). + */ + private final ArrowStackLabel rightArrows; + /** The input field for the syntactical translation text. */ + private final ScaledTextField synTranslationField; + /** The input field for the semantical translation text. */ + private final ScaledTextField semTranslationField; + /** + * The view element allowing this {@link Proposition} to be selected for any more complex operations involving multiple model elements. + */ + private final JCheckBox checkBox = new JCheckBox(); + + /** + * Create a {@link SynProposition} representing the given {@link Proposition} on the specified indentation {@code level}. + * + * @param viewReference the containing view, providing access to higher functions + * @param represented represented {@link Proposition} to set + * @param propositionIndex index of the represented proposition in the origin text (including parts after arrows) + * @param level number of indentations to set + * @return created {@link SynProposition} + */ + public static ViewProposition createSynPropositionByLevel(final IPericopeView viewReference, final Proposition represented, + final int propositionIndex, final int level) { + final ViewProposition created = new ViewProposition(viewReference, represented, propositionIndex); + if (level > 0 && created.indentationArea != null) { + created.indentationArea.setPreferredSize(ViewProposition.createIndentation(level)); + } + return created; + } + + /** + * Create a {@link SynProposition} representing the given {@link Proposition}, which is the {@code partAfterArrow} for the other given + * {@link SynProposition}, determining the created elements indentation. + * + * @param viewReference the containing view, providing access to higher functions + * @param represented represented {@link Proposition} part to set + * @param propositionIndex index of the represented proposition in the origin text (including parts after arrows) + * @param partBeforeArrow view representation of the {@code partBeforeArrow} + * @return created {@link SynProposition} + */ + public static ViewProposition createSynPropositionByPartBeforeArrow(final IPericopeView viewReference, final Proposition represented, + final int propositionIndex, final ViewProposition partBeforeArrow) { + final ViewProposition created = new ViewProposition(viewReference, represented, propositionIndex); + if (created.indentationArea != null) { + created.indentationArea.setPreferredSize(ViewProposition.createIndentationAfterArrow(partBeforeArrow)); + } + return created; + } + + /** + * creates a {@link Dimension} for the indentation by setting its width regarding to the specified level. + * + * @param level number of indentations to be contained + * @return {@link Dimension} representing the indentation + */ + private static Dimension createIndentation(final int level) { + return new Dimension(HmxGeneralOption.INDENTATION_WIDTH.getValueAsInteger() * level, 1); + } + + /** + * Create a {@link Dimension} for the indentation by settings its width regarding to the width of the view representation of the + * {@code partBeforeArrow}. + * + * @param partBeforeArrow view representation of the {@code partBeforeArrow} + * @return {@link Dimension} representing the indentation + */ + private static Dimension createIndentationAfterArrow(final ViewProposition partBeforeArrow) { + final int partBeforeArrowIndentation = partBeforeArrow.indentationArea == null ? 0 : partBeforeArrow.indentationArea.getPreferredSize().width; + return new Dimension(partBeforeArrowIndentation + partBeforeArrow.leftArrows.getPreferredSize().width + + partBeforeArrow.itemArea.getPreferredSize().width, 1); + } + + /** + * Constructor: creating an {@link ViewProposition} by setting all values derived from the represented {@link Proposition}. + * + * @param viewReference the analysis view that will contain this component + * @param represented represented {@link Proposition} to set + * @param propositionIndex index of the represented proposition in the origin text (including parts after arrows) + */ + public ViewProposition(final IPericopeView viewReference, final Proposition represented, final int propositionIndex) { + super(new GridBagLayout()); + this.viewReference = viewReference; + this.represented = represented; + this.propositionIndex = propositionIndex; + final boolean leftAligned = viewReference.getModelHandler().getModel().isLeftToRightOriented(); + this.defaultBorderCommented = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), + BorderFactory.createCompoundBorder( + BorderFactory.createMatteBorder(2, leftAligned ? 1 : 0, 2, leftAligned ? 0 : 1, + HmxGeneralOption.COMMENTED_BORDER_COLOR.getValueAsColor()), + BorderFactory.createEmptyBorder(0, leftAligned ? 1 : 2, 4, leftAligned ? 2 : 1))); + final ComponentOrientation orientation = leftAligned ? ComponentOrientation.LEFT_TO_RIGHT : ComponentOrientation.RIGHT_TO_LEFT; + this.setComponentOrientation(orientation); + this.contentPane.setComponentOrientation(orientation); + this.itemArea.setComponentOrientation(orientation); + this.leftArrows = new ArrowStackLabel(true, 0); + this.rightArrows = new ArrowStackLabel(false, 0); + + final IAnalysisViewSettings viewSettings = viewReference.getViewSettings(); + final GridBagConstraints checkBoxConstraints = new GridBagConstraints(); + checkBoxConstraints.gridx = 0; + checkBoxConstraints.gridy = 1; + if (this.represented.getPartBeforeArrow() == null && (viewSettings.isShowingPropositionIndentations() + || viewSettings.isShowingRelations() && this.represented.getSuperOrdinatedRelation() == null)) { + this.checkBox.setName("Check Box"); + this.contentPane.add(this.checkBox, checkBoxConstraints); + } else { + final JPanel checkBoxDummy = new JPanel(null); + checkBoxDummy.setPreferredSize(this.checkBox.getPreferredSize()); + this.contentPane.add(checkBoxDummy, checkBoxConstraints); + } + + this.labelField = this.initLabel(viewSettings); + this.indentationArea = this.initIndentationArea(viewSettings); + this.functionLabel = this.initFunctionLabel(); + if (viewSettings.isShowingClauseItems()) { + this.originText = null; + this.items = new LinkedList(); + } else { + this.originText = new ScaledTextField(); + this.items = null; + } + this.initOriginTextArea(); + this.synTranslationField = this.initSynTranslationField(viewSettings); + this.semTranslationField = this.initSemTranslationField(viewSettings); + this.add(this.contentPane); + // create expanding panel on the right side of the proposition + final GridBagConstraints rightSpacingConstraints = new GridBagConstraints(); + rightSpacingConstraints.fill = GridBagConstraints.HORIZONTAL; + rightSpacingConstraints.weightx = 1; + rightSpacingConstraints.gridx = 1; + rightSpacingConstraints.gridy = 0; + final JPanel rightSpacing = new JPanel(null); + rightSpacing.setPreferredSize(new Dimension(1, 1)); + this.add(rightSpacing, rightSpacingConstraints); + this.setDefaultBorder(); + this.refresh(); + this.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(final MouseEvent event) { + viewReference.handleSelectedCommentable(ViewProposition.this); + this.mouseReleased(event); + } + + @Override + public void mouseReleased(final MouseEvent event) { + if (event.isPopupTrigger()) { + final ContextMenuBuilder contextMenu; + if (ViewProposition.this.getRepresented().getPartBeforeArrow() == null) { + contextMenu = ContextMenuFactory.createPropositionPopup(viewReference, represented); + } else { + contextMenu = ContextMenuFactory.createPropositionAfterArrowPopup(viewReference, represented); + } + if (!contextMenu.isEmpty()) { + ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); + } + } + } + }); + } + + /** + * Initialize the label {@link ScaledTextField input}. + * + * @param viewSettings settings to apply + * @return created label input (can be {@code null}) + */ + private ScaledTextField initLabel(final IAnalysisViewSettings viewSettings) { + final ScaledTextField label; + if (viewSettings.isShowingPropositionLabels()) { + label = new ScaledTextField(); + label.setName("Label Input"); + label.setColumns(Proposition.MAX_LABEL_LENGTH - 1); + label.setDocument(new Validation(Proposition.MAX_LABEL_LENGTH)); + label.addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(final FocusEvent event) { + ViewProposition.this.submitLabelChanges(); + } + }); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = 1; + constraints.gridy = 1; + this.contentPane.add(label, constraints); + } else { + label = null; + } + return label; + } + + /** + * Initialize an expanding {@link JPanel} for the proposition's indentation. + * + * @param viewSettings settings to apply + * @return created panel (can be {@code null}) + */ + private JPanel initIndentationArea(final IAnalysisViewSettings viewSettings) { + final JPanel indentationAreaPanel; + if (viewSettings.isShowingPropositionIndentations()) { + indentationAreaPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.VERTICAL; + constraints.weighty = 1; + constraints.gridheight = 4; + constraints.gridx = 2; + constraints.gridy = 0; + this.contentPane.add(indentationAreaPanel, constraints); + } else { + indentationAreaPanel = null; + } + return indentationAreaPanel; + } + + /** + * Add a label representing the syntactical indentation function of the represented proposition, if any. + * + * @return created label (can be {@code null}) + */ + private ScaledLabel initFunctionLabel() { + final ScaledLabel label; + if (this.indentationArea == null || !(this.getRepresented().getParent() instanceof Proposition)) { + label = null; + } else { + final GridBagConstraints spacing = new GridBagConstraints(); + spacing.weightx = 1; + this.indentationArea.add(new JPanel(null), spacing); + + label = new ScaledLabel(" "); + final SyntacticalFunction function = this.getRepresented().getFunction(); + label.setIcon(new VTextIcon(label, function == null ? " " : function.getCode(), VTextIcon.Rotate.NONE)); + final int border = (ViewProposition.createIndentation(1).width - label.getPreferredSize().width) / 2; + final GridBagConstraints verticalSpan = new GridBagConstraints(); + verticalSpan.anchor = GridBagConstraints.BASELINE_TRAILING; + verticalSpan.weighty = 1; + verticalSpan.insets = new Insets(0, border, 0, border); + this.indentationArea.add(label, verticalSpan); + } + return label; + } + + /** + * Initialize the top right part of the {@link Proposition} containing a panel for the origin text as well as arrows on the left and on the right + * side of it. + */ + private void initOriginTextArea() { + if (this.represented.getPartBeforeArrow() != null) { + // leftArrows + final GridBagConstraints arrowConstraints = new GridBagConstraints(); + arrowConstraints.anchor = GridBagConstraints.CENTER; + arrowConstraints.gridx = 3; + arrowConstraints.gridy = 0; + arrowConstraints.gridheight = 2; + this.contentPane.add(this.leftArrows, arrowConstraints); + } + // itemArea + if (this.originText != null) { + this.originText.setFont(this.viewReference.getModelHandler().getModel().getFont()); + this.originText.setEditable(false); + this.originText.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), + BorderFactory.createEmptyBorder(2, 5, 2, 5))); + this.itemArea.add(this.originText); + } + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = 4; + constraints.gridy = 0; + constraints.gridheight = 2; + this.contentPane.add(this.itemArea, constraints); + if (this.represented.getPartAfterArrow() != null) { + // rightArrows + final GridBagConstraints arrowConstraints = new GridBagConstraints(); + arrowConstraints.anchor = GridBagConstraints.CENTER; + arrowConstraints.gridx = 5; + arrowConstraints.gridy = 0; + arrowConstraints.gridheight = 2; + this.contentPane.add(this.rightArrows, arrowConstraints); + } + // just to make sure rightArrows are behind the itemArea in case of an expanded translation field + final GridBagConstraints rightSpacingConstraints = new GridBagConstraints(); + rightSpacingConstraints.fill = GridBagConstraints.HORIZONTAL; + rightSpacingConstraints.weightx = 1; + rightSpacingConstraints.gridx = 6; + rightSpacingConstraints.gridy = 0; + rightSpacingConstraints.gridheight = 2; + final JPanel rightSpacing = new JPanel(null); + rightSpacing.setPreferredSize(new Dimension(1, 1)); + this.contentPane.add(rightSpacing, rightSpacingConstraints); + } + + /** + * Initialize the syntactic translation {@link ScaledTextField input} on the bottom right of the {@link Proposition}. + * + * @param viewSettings settings to apply + * @return created translation input (can be {@code null}) + */ + private ScaledTextField initSynTranslationField(final IAnalysisViewSettings viewSettings) { + final ScaledTextField translationField; + if (viewSettings.isShowingSyntacticTranslations()) { + translationField = new ScaledTextField(); + translationField.setName("Syn Translation Input"); + translationField.setDocument(new Validation(Proposition.MAX_TRANSLATION_LENGTH)); + translationField.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(final FocusEvent event) { + ViewProposition.this.submitSynTranslationChanges(); + } + }); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = 4; + constraints.gridx = 3; + constraints.gridy = 2; + this.contentPane.add(translationField, constraints); + } else { + translationField = null; + } + return translationField; + } + + /** + * Initialize the semantic translation {@link ScaledTextField input} on the bottom right of the {@link Proposition}. + * + * @param viewSettings settings to apply + * @return created translation input (can be {@code null}) + */ + private ScaledTextField initSemTranslationField(final IAnalysisViewSettings viewSettings) { + final ScaledTextField translationField; + if (viewSettings.isShowingSemanticTranslations()) { + translationField = new ScaledTextField(); + translationField.setName("Sem Translation Input"); + translationField.setDocument(new Validation(Proposition.MAX_TRANSLATION_LENGTH)); + translationField.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(final FocusEvent event) { + ViewProposition.this.submitSemTranslationChanges(); + } + }); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = 4; + constraints.gridx = 3; + constraints.gridy = 3; + this.contentPane.add(translationField, constraints); + } else { + translationField = null; + } + return translationField; + } + + /** + * Ensure that any pending changes (e.g. in the label or translation fields) are being submitted to the model handler. + */ + public void submitChangesToModel() { + if (this.labelField != null) { + this.submitLabelChanges(); + } + if (this.synTranslationField != null) { + this.submitSynTranslationChanges(); + } + if (this.semTranslationField != null) { + this.submitSemTranslationChanges(); + } + } + + /** + * Ensure that any changes in the label field are submitted to the model. + */ + final void submitLabelChanges() { + // only transfer if necessary + final String labelText = this.labelField.getText(); + if (!ComparisonUtil.isNullOrEmptyAwareEqual(this.represented.getLabel(), labelText)) { + this.viewReference.getModelHandler().setLabelText(this.represented, labelText); + } + } + + /** + * Ensure that any changes in the syntactic translation field are submitted to the model. + */ + final void submitSynTranslationChanges() { + final String translationText = this.synTranslationField.getText(); + // only transfer if necessary + if (!ComparisonUtil.isNullOrEmptyAwareEqual(translationText, this.getRepresented().getSynTranslation())) { + this.viewReference.getModelHandler().setSynTranslation(this.getRepresented(), translationText); + } + } + + /** + * Ensure that any changes in the semantic translation field are submitted to the model. + */ + final void submitSemTranslationChanges() { + final String translationText = this.semTranslationField.getText(); + // only transfer if necessary + if (!ComparisonUtil.isNullOrEmptyAwareEqual(translationText, this.getRepresented().getSemTranslation())) { + this.viewReference.getModelHandler().setSemTranslation(this.getRepresented(), translationText); + } + } + + /** + * Setter for the number of displayed upward arrows on the left of the item area. + * + * @param count number of displayed arrows to set + */ + public void setLeftArrowCount(final int count) { + this.leftArrows.setArrowCount(count); + } + + /** + * Setter for the number of displayed downward arrows on the right of the item area. + * + * @param count number of displayed arrows to set + */ + public void setRightArrowCount(final int count) { + this.rightArrows.setArrowCount(count); + } + + /** + * Getter for the represented {@link Proposition}. + * + * @return represented model element + */ + @Override + public Proposition getRepresented() { + return this.represented; + } + + /** + * Fully update the contents of the displayed proposition without rebuilding it. + * + * @return whether the update was successful, otherwise a proper rebuild is required + */ + public boolean refresh() { + this.refreshLabelText(); + this.refreshFunction(); + this.refreshTranslation(); + this.refreshComment(); + if (this.originText == null) { + this.itemArea.removeAll(); + this.items.clear(); + for (final ClauseItem item : this.represented.getItems()) { + final ViewClauseItem singleItem = new ViewClauseItem(this.viewReference, item); + this.items.add(singleItem); + this.itemArea.add(singleItem); + } + } else { + final StringBuffer text = new StringBuffer(" "); + for (final ClauseItem singleItem : this.getRepresented()) { + text.append(singleItem.getOriginText()).append(' '); + } + this.originText.setText(text.toString()); + this.originText.setSize(this.originText.getPreferredSize()); + } + return true; + } + + /** + * Update the displayed identifier text to match the value in the represented {@link Proposition}. + */ + void refreshLabelText() { + if (this.labelField != null) { + this.labelField.setText(this.represented.getLabel()); + } + } + + /** + * Update the indentation function (in relation to the parent {@link Proposition}) to match the represented {@link Proposition}'s function value. + */ + void refreshFunction() { + if (this.functionLabel != null && this.getRepresented().getParent() instanceof Proposition) { + final SyntacticalFunction function = this.getRepresented().getFunction(); + ((VTextIcon) this.functionLabel.getIcon()).setLabel(function == null ? " " : function.getCode()); + } + } + + /** + * sets the semantical translation text regarding the stored translation in the represented {@link Proposition} and fits the {@link Proposition} + * to the possibly expanded translation field size. + */ + void refreshTranslation() { + if (this.synTranslationField == null && this.semTranslationField == null) { + // nothing to refresh here + return; + } + final Dimension preferredSynFieldSize; + if (this.synTranslationField == null) { + preferredSynFieldSize = new Dimension(0, 0); + } else { + this.synTranslationField.setText(this.getRepresented().getSynTranslation()); + preferredSynFieldSize = this.synTranslationField.getPreferredSize(); + } + final Dimension preferredSemFieldSize; + if (this.semTranslationField == null) { + preferredSemFieldSize = new Dimension(0, 0); + } else { + this.semTranslationField.setText(this.getRepresented().getSemTranslation()); + preferredSemFieldSize = this.semTranslationField.getPreferredSize(); + } + // if the translation text wants more space, it gets more + final int translationFieldPreference = Math.max(preferredSynFieldSize.width, preferredSemFieldSize.width); + final int translationFieldWidth = Math.max(translationFieldPreference, this.itemArea.getPreferredSize().width); + if (this.synTranslationField != null) { + this.synTranslationField.setSize(translationFieldWidth, preferredSynFieldSize.height); + } + if (this.semTranslationField != null) { + this.semTranslationField.setSize(translationFieldWidth, preferredSemFieldSize.height); + } + // enlarge the containing proposition + this.contentPane.setSize(this.contentPane.getPreferredSize()); + // make sure it is still displayed + this.itemArea.validate(); + } + + /** + * resets the tool tip info containing the comment text regarding its value in the represented {@link Proposition}. + */ + void refreshComment() { + final String comment = this.getRepresented().getComment(); + if (comment == null || comment.isEmpty()) { + this.setToolTipText(null); + } else { + this.setToolTipText(comment); + } + } + + /** + * Update the view representation of the given {@link ClauseItem}. + * + * @param target model element to update representation of + */ + public void refreshClauseItem(final ClauseItem target) { + if (this.items != null) { + for (final ViewClauseItem singleItem : this.items) { + if (singleItem.getRepresented() == target) { + singleItem.refresh(); + break; + } + } + } + } + + @Override + public boolean isChecked() { + return this.checkBox.isSelected(); + } + + @Override + public void setNotChecked() { + this.checkBox.setSelected(false); + } + + @Override + public int getDepth() { + return 0; + } + + @Override + public double getConnectY() { + return 0.5 + this.propositionIndex; + } + + @Override + public void setDefaultBorder() { + final boolean containsComment = this.represented.getComment() != null && !this.represented.getComment().trim().isEmpty(); + this.setContentBorder(containsComment ? this.defaultBorderCommented : ViewProposition.DEFAULT_BORDER); + } + + @Override + public void setCommentBorder() { + this.setContentBorder(ViewProposition.COMMENT_BORDER); + } + + /** + * Apply the given border any ensure that any contained {@link ViewClauseItem}s are still properly shown. + * + * @param border border to apply + */ + private void setContentBorder(final Border border) { + this.contentPane.setBorder(border); + // without these visibility changes the item area may disappear + this.itemArea.setVisible(false); + // make sure the item area is still visible + this.itemArea.setVisible(true); + if (this.items != null) { + this.itemArea.revalidate(); + for (final ViewClauseItem singleItem : this.items) { + singleItem.revalidate(); + } + } + } + + /** + * Add the specified {@link MouseListener} to all components included except the single {@link SynItem}s in the syntactical analysis view. + * + * @param listener listener to add + */ + @Override + public synchronized void addMouseListener(final MouseListener listener) { + super.addMouseListener(listener); + if (this.labelField != null) { + this.labelField.addMouseListener(listener); + } + if (this.indentationArea != null) { + this.indentationArea.addMouseListener(listener); + } + this.leftArrows.addMouseListener(listener); + this.itemArea.addMouseListener(listener); + if (this.originText != null) { + this.originText.addMouseListener(listener); + } + this.rightArrows.addMouseListener(listener); + if (this.synTranslationField != null) { + this.synTranslationField.addMouseListener(listener); + } + if (this.semTranslationField != null) { + this.semTranslationField.addMouseListener(listener); + } + } + + /** + * Ses the specified tool tip text to all of its components except the single {@link SynItem}s in the syntactical analysis view. + * + * @param toolTip tool tip text to set + */ + @Override + public synchronized void setToolTipText(final String toolTip) { + super.setToolTipText(toolTip); + if (this.labelField != null) { + this.labelField.setToolTipText(toolTip); + } + if (this.indentationArea != null) { + this.indentationArea.setToolTipText(toolTip); + } + this.leftArrows.setToolTipText(toolTip); + this.itemArea.setToolTipText(toolTip); + if (this.originText != null) { + this.originText.setToolTipText(toolTip); + } + this.rightArrows.setToolTipText(toolTip); + if (this.synTranslationField != null) { + this.synTranslationField.setToolTipText(toolTip); + } + if (this.semTranslationField != null) { + this.semTranslationField.setToolTipText(toolTip); + } + } +} diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelation.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelation.java similarity index 82% rename from scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelation.java rename to scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelation.java index def5469..67e33d7 100755 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelation.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelation.java @@ -46,9 +46,7 @@ import org.hmx.scitos.hmx.domain.model.Proposition; import org.hmx.scitos.hmx.domain.model.Relation; import org.hmx.scitos.hmx.view.ContextMenuFactory; -import org.hmx.scitos.hmx.view.IPericopeView; -import org.hmx.scitos.hmx.view.swing.components.SemAnalysisPanel; -import org.hmx.scitos.hmx.view.swing.components.SemControl; +import org.hmx.scitos.hmx.view.swing.components.AnalysisPanel; import org.hmx.scitos.view.ContextMenuBuilder; import org.hmx.scitos.view.swing.ContextMenuPopupBuilder; import org.hmx.scitos.view.swing.components.ScaledTextField; @@ -57,7 +55,7 @@ * View representation of a {@link Relation} drawing colored lines to show the relations between its subordinated {@link IConnectable}s and * {@link JTextField}s above displaying their roles. */ -public final class SemRelation extends AbstractCommentable implements IConnectable { +public final class ViewRelation extends AbstractCommentable implements IConnectable { /** half thickness of the displayed lines. */ protected static final int HALF_LINE_THICKNESS = 2; @@ -68,8 +66,8 @@ public final class SemRelation extends AbstractCommentable implements private final Border defaultBorder; /** Colored, raised bevel border, when not selected and with assigned comment. */ private final Border defaultCommentedBorder; - /** The semantical analysis this is displayed in. */ - final SemAnalysisPanel semArea; + /** The analysis view this is displayed in. */ + final AnalysisPanel analysisPanel; /** The view representations of the sub ordinated associates. */ private final List> viewAssociates; /** The text fields displaying the respective roles of the sub ordinated associates. */ @@ -85,9 +83,9 @@ public final class SemRelation extends AbstractCommentable implements /** Whether the role labels should be shown above the relation lines. Otherwise, they will be shown on top of the lines (i.e. hiding them). */ private final boolean showRoleAboveLine; /** - * check box to select this {@link SemRelation}. + * check box to select this {@link ViewRelation}. */ - private final JCheckBox checkBox = new JCheckBox(); + private final JCheckBox checkBox; /** The depth in the relation tree of the current analysis. */ private final int depth; /** @@ -106,30 +104,31 @@ public final class SemRelation extends AbstractCommentable implements /** * Constructor. * - * @param viewReference - * the view providing access to the project's model handler and handling the comments on model elements - * @param semArea - * semantical analysis view to be contained in + * @param analysisPanel + * analysis view to be contained in * @param represented * model {@link Relation} to display * @param foldedLevels * levels to suppress display of semantic roles on */ - public SemRelation(final IPericopeView viewReference, final SemAnalysisPanel semArea, final Relation represented, - final Collection foldedLevels) { + public ViewRelation(final AnalysisPanel analysisPanel, final Relation represented, final Collection foldedLevels) { super(null); - this.semArea = semArea; + this.analysisPanel = analysisPanel; this.represented = represented; - this.leftAligned = viewReference.getModelHandler().getModel().isLeftToRightOriented(); + this.leftAligned = analysisPanel.getModelHandler().getModel().isLeftToRightOriented(); final List modelAssociates = represented.getAssociates(); - this.showRoleAboveLine = viewReference.isShowingPropositionTranslations(); + this.showRoleAboveLine = analysisPanel.getViewSettings().isShowingSemanticTranslations() + || analysisPanel.getViewSettings().isShowingSyntacticTranslations(); this.viewAssociates = new ArrayList>(modelAssociates.size()); for (final AbstractConnectable singleAssociate : modelAssociates) { - this.viewAssociates.add(SemControl.getRepresentative(semArea, singleAssociate)); + this.viewAssociates.add(this.analysisPanel.getRepresentative(singleAssociate)); } this.depth = represented.getTreeDepth(); if (represented.getSuperOrdinatedRelation() == null) { + this.checkBox = new JCheckBox(); this.add(this.checkBox); + } else { + this.checkBox = null; } if (foldedLevels.contains(this.depth)) { this.roleFields = null; @@ -151,14 +150,14 @@ public SemRelation(final IPericopeView viewReference, final SemAnalysisPanel sem this.add(roleField); } } - this.firstGridY = SemControl.getRepresentative(semArea, represented.getFirstPropositionContained()).getConnectY(); - this.lastGridY = SemControl.getRepresentative(semArea, represented.getLastPropositionContained()).getConnectY(); + this.firstGridY = this.analysisPanel.getRepresentative(represented.getFirstPropositionContained()).getConnectY(); + this.lastGridY = this.analysisPanel.getRepresentative(represented.getLastPropositionContained()).getConnectY(); this.refreshRoles(); this.setToolTipText(represented.getComment()); this.defaultBorder = - BorderFactory.createEmptyBorder(SemRelation.COMMENT_BORDER.getBorderInsets(this).top, 0, - SemRelation.COMMENT_BORDER.getBorderInsets(this).bottom, 0); - final Insets borderInsets = SemRelation.COMMENT_BORDER.getBorderInsets(this); + BorderFactory.createEmptyBorder(ViewRelation.COMMENT_BORDER.getBorderInsets(this).top, 0, + ViewRelation.COMMENT_BORDER.getBorderInsets(this).bottom, 0); + final Insets borderInsets = ViewRelation.COMMENT_BORDER.getBorderInsets(this); this.defaultCommentedBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(borderInsets.top - 2, this.leftAligned ? (borderInsets.left - 1) : 0, borderInsets.bottom - 2, this.leftAligned ? 0 : (borderInsets.right - 1)), BorderFactory @@ -170,14 +169,14 @@ public SemRelation(final IPericopeView viewReference, final SemAnalysisPanel sem @Override public void mousePressed(final MouseEvent event) { - viewReference.handleSelectedCommentable(SemRelation.this); + analysisPanel.handleSelectedCommentable(ViewRelation.this); this.mouseReleased(event); } @Override public void mouseReleased(final MouseEvent event) { if (event.isPopupTrigger()) { - final ContextMenuBuilder contextMenu = ContextMenuFactory.createSemRelationPopup(viewReference, represented); + final ContextMenuBuilder contextMenu = ContextMenuFactory.createRelationPopup(analysisPanel, represented); ContextMenuPopupBuilder.buildSwingPopupMenu(contextMenu).show(event.getComponent(), event.getX(), event.getY()); } } @@ -207,28 +206,26 @@ protected void paintComponent(final Graphics graphics) { final int gridHeight = (int) (this.lastGridY - this.firstGridY) + 1; final int height = this.getSize().height; final double partY = height / (double) gridHeight; - int startX; - if (this.represented.getSuperOrdinatedRelation() == null) { + final int startX; + if (this.checkBox != null) { final Dimension boxSize = this.checkBox.getPreferredSize(); int posX; if (this.leftAligned) { - posX = SemRelation.HALF_LINE_THICKNESS; - startX = (boxSize.width + (2 * SemRelation.HALF_LINE_THICKNESS)); + posX = ViewRelation.HALF_LINE_THICKNESS; + startX = boxSize.width + (2 * ViewRelation.HALF_LINE_THICKNESS); } else { - posX = this.getSize().width - (boxSize.width + SemRelation.HALF_LINE_THICKNESS); - startX = this.getSize().width - (boxSize.width + (2 * SemRelation.HALF_LINE_THICKNESS)); + posX = this.getSize().width - (boxSize.width + ViewRelation.HALF_LINE_THICKNESS); + startX = this.getSize().width - (boxSize.width + (2 * ViewRelation.HALF_LINE_THICKNESS)); } // insert check box - this.checkBox.setBounds(posX, (int) (((this.connectY - (this.firstGridY - 0.5)) * partY) - (boxSize.height / 2.)), boxSize.width, - boxSize.height); + final int posY = (int) (((this.connectY - (this.firstGridY - 0.5)) * partY) - (boxSize.height / 2.)); + this.checkBox.setBounds(posX, posY, boxSize.width, boxSize.height); + } else if (this.leftAligned) { + startX = 0; } else { - if (this.leftAligned) { - startX = 0; - } else { - startX = this.getSize().width; - } + startX = this.getSize().width; } - final int topBorder = SemRelation.COMMENT_BORDER.getBorderInsets(this).top; + final int topBorder = ViewRelation.COMMENT_BORDER.getBorderInsets(this).top; final int lineLeftEnd; final int lineWidth; final List horizontalLines = new ArrayList(this.viewAssociates.size()); @@ -242,7 +239,7 @@ protected void paintComponent(final Graphics graphics) { // draw horizontal lines for (final IConnectable singleAssociate : this.viewAssociates) { final int lineY = (int) ((singleAssociate.getConnectY() - this.firstGridY + 0.5) * partY - (topBorder / 2.)); - final Rectangle singleHorizontal = new Rectangle(lineLeftEnd, lineY, lineWidth, (2 * SemRelation.HALF_LINE_THICKNESS)); + final Rectangle singleHorizontal = new Rectangle(lineLeftEnd, lineY, lineWidth, (2 * ViewRelation.HALF_LINE_THICKNESS)); graphics2D.draw(singleHorizontal); graphics2D.fill(singleHorizontal); horizontalLines.add(lineY); @@ -252,27 +249,27 @@ protected void paintComponent(final Graphics graphics) { if (this.leftAligned) { verticalPos = lineLeftEnd; } else { - verticalPos = startX - (2 * SemRelation.HALF_LINE_THICKNESS); + verticalPos = startX - (2 * ViewRelation.HALF_LINE_THICKNESS); } final Rectangle verticalLine = - new Rectangle(verticalPos, horizontalLines.get(0), (2 * SemRelation.HALF_LINE_THICKNESS), (horizontalLines.get(horizontalLines - .size() - 1) - horizontalLines.get(0)) + (2 * SemRelation.HALF_LINE_THICKNESS)); + new Rectangle(verticalPos, horizontalLines.get(0), (2 * ViewRelation.HALF_LINE_THICKNESS), (horizontalLines.get(horizontalLines + .size() - 1) - horizontalLines.get(0)) + (2 * ViewRelation.HALF_LINE_THICKNESS)); graphics2D.draw(verticalLine); graphics2D.fill(verticalLine); if (this.roleFields != null) { - int fieldX = startX + 2 + (3 * SemRelation.HALF_LINE_THICKNESS); + int fieldX = startX + 2 + (3 * ViewRelation.HALF_LINE_THICKNESS); // insert role text fields for (int i = 0; i < this.roleFields.size(); i++) { final JTextField roleField = this.roleFields.get(i); final int fieldHeight = roleField.getPreferredSize().height; final int fieldWidth = roleField.getPreferredSize().width + 5; if (!this.leftAligned) { - fieldX = startX - (2 + (3 * SemRelation.HALF_LINE_THICKNESS) + fieldWidth); + fieldX = startX - (2 + (3 * ViewRelation.HALF_LINE_THICKNESS) + fieldWidth); } int fieldY = horizontalLines.get(i); if (this.showRoleAboveLine) { // ensure the field is shown above the line with spacing of 2px - fieldY -= fieldHeight + SemRelation.HALF_LINE_THICKNESS + 2; + fieldY -= fieldHeight + ViewRelation.HALF_LINE_THICKNESS + 2; } else { // display the field directly over the line (half above/half below) fieldY -= fieldHeight / 2; @@ -283,7 +280,7 @@ protected void paintComponent(final Graphics graphics) { } /** - * Calculate the minimum preferred width of the {@link SemRelation} regarding the {@link JTextField}s containing the roles and the additional + * Calculate the minimum preferred width of the {@link ViewRelation} regarding the {@link JTextField}s containing the roles and the additional * border spacings. * * @return minimum preferred width @@ -298,10 +295,10 @@ private int calculateWidth() { } // regard the additional checkbox if the relation is checkable if (this.represented.getSuperOrdinatedRelation() == null) { - result += this.checkBox.getPreferredSize().width + (2 * SemRelation.HALF_LINE_THICKNESS); + result += this.checkBox.getPreferredSize().width + (2 * ViewRelation.HALF_LINE_THICKNESS); } // add the default left and right spacing - return result + 11 + (4 * SemRelation.HALF_LINE_THICKNESS); + return result + 11 + (4 * ViewRelation.HALF_LINE_THICKNESS); } @Override @@ -309,11 +306,6 @@ public Relation getRepresented() { return this.represented; } - @Override - public void setCheckBoxVisible(final boolean val) { - this.checkBox.setVisible(val); - } - @Override public boolean isChecked() { return this.checkBox.isSelected(); @@ -346,7 +338,7 @@ public void setDefaultBorder() { @Override public void setCommentBorder() { - this.setBorder(SemRelation.COMMENT_BORDER); + this.setBorder(ViewRelation.COMMENT_BORDER); } @Override @@ -425,7 +417,7 @@ private void refreshRoles() { } } final Dimension preferred = this.getPreferredSize(); - this.setSize(new Dimension(preferred.width + (2 * SemRelation.HALF_LINE_THICKNESS), preferred.height)); + this.setSize(new Dimension(preferred.width + (2 * ViewRelation.HALF_LINE_THICKNESS), preferred.height)); // recalculate connectY final boolean firstAssociateHighWeight = this.viewAssociates.get(0).getRepresented().getRole().isHighWeight(); diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelationExtender.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelationExtender.java similarity index 82% rename from scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelationExtender.java rename to scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelationExtender.java index 881abd2..535facb 100755 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/SemRelationExtender.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/elements/ViewRelationExtender.java @@ -29,10 +29,10 @@ import org.hmx.scitos.hmx.core.option.HmxGeneralOption; /** - * simple {@link JPanel} with a colored horizontal line in a vertically centered position to fill gaps between a {@link SemRelation} and its + * simple {@link JPanel} with a colored horizontal line in a vertically centered position to fill gaps between a {@link ViewRelation} and its * subordinated elements. */ -public final class SemRelationExtender extends JPanel { +public final class ViewRelationExtender extends JPanel { /** * relation line color. @@ -42,7 +42,7 @@ public final class SemRelationExtender extends JPanel { /** * creates a new {@link SemRelationExtender} without any special functions. */ - public SemRelationExtender() { + public ViewRelationExtender() { super(null); this.setBorder(null); this.color = HmxGeneralOption.RELATION_COLOR.getValueAsColor(); @@ -58,8 +58,8 @@ protected void paintComponent(final Graphics graphics) { final Graphics2D graphics2D = (Graphics2D) graphics; graphics2D.setColor(this.color); final Rectangle line = - new Rectangle(0, (this.getSize().height - SemRelation.COMMENT_BORDER.getBorderInsets(this).bottom) / 2, this.getSize().width, - (2 * SemRelation.HALF_LINE_THICKNESS)); + new Rectangle(0, (this.getSize().height - ViewRelation.COMMENT_BORDER.getBorderInsets(this).bottom) / 2, this.getSize().width, + (2 * ViewRelation.HALF_LINE_THICKNESS)); graphics2D.draw(line); graphics2D.fill(line); } diff --git a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/option/HmxGeneralOptionPanel.java b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/option/HmxGeneralOptionPanel.java index 65e3ac0..a3f6ab9 100644 --- a/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/option/HmxGeneralOptionPanel.java +++ b/scitos.hmx/scitos.hmx.view/src/main/java/org/hmx/scitos/hmx/view/swing/option/HmxGeneralOptionPanel.java @@ -69,11 +69,6 @@ public final class HmxGeneralOptionPanel extends AbstractSimpleOptionPanelswitch to Semantical Analysis *
  • enter other character in label input
  • *
  • hide proposition labels
  • - *
  • show proposition translations
  • *
  • switch back to Syntactical Analysis
  • *
  • show proposition labels
  • * @@ -149,73 +148,61 @@ public void testVisibilityToggles() { // #4 ignore project info input dialog this.getButtonByText(Message.CANCEL).click(); // #5 enter single character as translation for first Proposition - this.getSynPropositionTranslationInput(0).enterText("T"); + this.getPropositionSynTranslationInput(0).enterText("T"); // #6 hide proposition translations - this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_PROPOSITION_TRANSLATIONS.get()).click(); + this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_SYNTACTIC_TRANSLATIONS.get()).click(); try { - this.getSynPropositionTranslationInput(0); + this.getPropositionSynTranslationInput(0); Assert.fail("The proposition's translation field should not be displayed."); } catch (final ComponentLookupException ex) { // the translation field is supposed to not be there } // #7 enter single character as label for first Proposition - this.getSynPropositionLabelInput(0).enterText("1"); + this.getPropositionLabelInput(0).enterText("1"); // #8 switch to Semantical Analysis - this.getSwitchAnalysisButton().click(); - this.getSemPropositionLabelInput(0).requireText("1"); - try { - this.getSemPropositionTranslationInput(0); - Assert.fail("The proposition's translation field should not be displayed."); - } catch (final ComponentLookupException ex) { - // the translation field is supposed to not be there - } + this.getSemanticalPresetToolBarButton().click(); + this.getPropositionSemTranslationInput(0).requireEmpty(); + this.getPropositionLabelInput(0).requireText("1"); // #9 enter other character in label input - this.getSemPropositionLabelInput(0).deleteText().enterText("2"); + this.getPropositionLabelInput(0).deleteText().enterText("2"); // #10 hide proposition labels this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_PROPOSITION_LABELS.get()).click(); try { - this.getSemPropositionLabelInput(0); + this.getPropositionLabelInput(0); Assert.fail("The proposition's label field should not be displayed."); } catch (final ComponentLookupException ex) { // the label field is supposed to not be there } - // #11 show proposition translations - this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_PROPOSITION_TRANSLATIONS.get()).click(); - this.getSemPropositionTranslationInput(0).requireEmpty(); - // #12 switch back to Syntactical Analysis - this.getSwitchAnalysisButton().click(); - this.getSynPropositionTranslationInput(0).requireText("T"); - - // #13 show proposition labels - this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_PROPOSITION_LABELS.get()).click(); - this.getSynPropositionLabelInput(0).requireText("2"); - } + // #11 switch back to Syntactical Analysis + this.getSyntacticalPresetToolBarButton().click(); + this.getPropositionSynTranslationInput(0).requireText("T"); - private JPanelFixture getSynProposition(final int index) { - return this.frame.panel(new OrdinalComponentMatcher(SynProposition.class, index, true)); + // #12 show proposition labels + this.frame.menuItemWithPath(Message.MENUBAR_VIEW.get(), HmxMessage.MENUBAR_TOGGLE_PROPOSITION_LABELS.get()).click(); + this.getPropositionLabelInput(0).requireText("2"); } - private JTextComponentFixture getSynPropositionTranslationInput(final int Index) { - return this.getSynProposition(Index).textBox("Translation Input"); + private JPanelFixture getProposition(final int index) { + return this.frame.panel(new OrdinalComponentMatcher(ViewProposition.class, index, true)); } - private JTextComponentFixture getSynPropositionLabelInput(final int Index) { - return this.getSynProposition(Index).textBox("Label Input"); + private JTextComponentFixture getPropositionLabelInput(final int Index) { + return this.getProposition(Index).textBox("Label Input"); } - private JPanelFixture getSemProposition(final int index) { - return this.frame.panel(new OrdinalComponentMatcher(SemProposition.class, index, true)); + private JTextComponentFixture getPropositionSynTranslationInput(final int Index) { + return this.getProposition(Index).textBox("Syn Translation Input"); } - private JTextComponentFixture getSemPropositionTranslationInput(final int Index) { - return this.getSemProposition(Index).textBox("Translation Input"); + private JTextComponentFixture getPropositionSemTranslationInput(final int Index) { + return this.getProposition(Index).textBox("Sem Translation Input"); } - private JTextComponentFixture getSemPropositionLabelInput(final int Index) { - return this.getSemProposition(Index).textBox("Label Input"); + private JToggleButtonFixture getSyntacticalPresetToolBarButton() { + return this.frame.toolBar().toggleButton("Preset: Syntactical"); } - private JButtonFixture getSwitchAnalysisButton() { - return this.frame.button("Switch Analysis Button"); + private JToggleButtonFixture getSemanticalPresetToolBarButton() { + return this.frame.toolBar().toggleButton("Preset: Semantical"); } } diff --git a/scitos.view/src/main/java/org/hmx/scitos/view/ContextMenuBuilder.java b/scitos.view/src/main/java/org/hmx/scitos/view/ContextMenuBuilder.java index b132879..056545c 100644 --- a/scitos.view/src/main/java/org/hmx/scitos/view/ContextMenuBuilder.java +++ b/scitos.view/src/main/java/org/hmx/scitos/view/ContextMenuBuilder.java @@ -56,7 +56,7 @@ public ContextMenuBuilder(final String caption) { /** * Getter for the title/caption of this menu. - * + * * @return title/caption of this menu */ public String getCaption() { @@ -65,7 +65,7 @@ public String getCaption() { /** * Append a submenu with the given title/caption. - * + * * @param subMenuCaption * caption of the sub menu * @return created sub menu (capable of holding an own set of {@link CMenuEntry entries}) @@ -76,7 +76,7 @@ public CMenu addMenu(final String subMenuCaption) { /** * Append an item with the given title/caption and the specified action. - * + * * @param itemCaption * caption of the single menu item * @param action @@ -89,7 +89,7 @@ public CMenuItem addItem(final String itemCaption, final CMenuItemAction action) /** * Append a separator to this menu. - * + * * @return visual grouping element */ public CMenuSeparator addSeparator() { @@ -112,7 +112,7 @@ protected E addEntry(final E entry) { /** * Getter for the list of contained menu entries. - * + * * @return list of all defined {@link CMenuEntry menu entries} */ public List getEntries() { @@ -124,6 +124,15 @@ public Iterator iterator() { return this.getEntries().iterator(); } + /** + * Returns {@code true} if this menu builder contains no entries. + * + * @return whether no entries have been added yet + */ + public boolean isEmpty() { + return this.entryList.isEmpty(); + } + /** * Common interface for all kinds of menu entries. */ @@ -155,7 +164,7 @@ public static final class CMenu extends ContextMenuBuilder implements CMenuEntry /** * Constructor. - * + * * @param caption * this sub menu's title/caption */ @@ -165,7 +174,7 @@ public static final class CMenu extends ContextMenuBuilder implements CMenuEntry /** * Check if this sub menu provides a value for the optional tool tip. - * + * * @return if the optional tool tip is set */ public boolean hasToolTip() { @@ -174,7 +183,7 @@ public boolean hasToolTip() { /** * Getter for the optional tool tip. - * + * * @return tool tip (can be {@code null}) */ public String getToolTip() { @@ -183,7 +192,7 @@ public String getToolTip() { /** * Setter for the optional tool tip. - * + * * @param toolTip * the tool tip text to set * @return self reference @@ -216,7 +225,7 @@ public static final class CMenuItem implements CMenuEntry { /** * Constructor. - * + * * @param caption * the item's title/caption * @param action @@ -229,7 +238,7 @@ public static final class CMenuItem implements CMenuEntry { /** * Getter for this item's title/caption. - * + * * @return caption of this menu item */ public String getCaption() { @@ -238,7 +247,7 @@ public String getCaption() { /** * Getter for the action to be executed when this item is selected by the user. - * + * * @return {@link CMenuItemAction executable action} on event of item selection */ public CMenuItemAction getAction() { @@ -247,7 +256,7 @@ public CMenuItemAction getAction() { /** * Check if this menu item provides a value for the optional tool tip. - * + * * @return if the optional tool tip is set */ public boolean hasToolTip() { @@ -256,7 +265,7 @@ public boolean hasToolTip() { /** * Getter for the optional tool tip. - * + * * @return the optional tool tip (can be {@code null}) */ public String getToolTip() { @@ -265,7 +274,7 @@ public String getToolTip() { /** * Setter for the optional tool tip. - * + * * @param toolTip * tool tip text to set * @return self reference @@ -277,7 +286,7 @@ public CMenuItem setToolTip(final String toolTip) { /** * Check if this menu item has a specific non-default {@link Font}. - * + * * @return if the optional, specific {@link Font} is set */ public boolean hasFont() { @@ -286,7 +295,7 @@ public boolean hasFont() { /** * Getter for the specific non-default {@link Font} for this menu item. - * + * * @param defaultFont * {@link Font} to use (or derive from) if no specific {@link Font} would have been set * @return specific {@link Font} to apply @@ -297,7 +306,7 @@ public Font getFont(final Font defaultFont) { /** * Setter for the specific non-default {@link Font} for this menu item. - * + * * @param font * specific Font to apply (can be {@code null}) * @return self reference @@ -309,7 +318,7 @@ public CMenuItem setFont(final Font font) { /** * Setter for the specific non-{@code plain} {@link Font} style. - * + * * @param fontStyle * differing {@link Font} style ({@link Font#BOLD BOLD}, {@link Font#ITALIC ITALIC}, or a combination of the two) * @return self reference diff --git a/scitos.view/src/main/java/org/hmx/scitos/view/ScitosIcon.java b/scitos.view/src/main/java/org/hmx/scitos/view/ScitosIcon.java index 154fdbd..2bb93c8 100644 --- a/scitos.view/src/main/java/org/hmx/scitos/view/ScitosIcon.java +++ b/scitos.view/src/main/java/org/hmx/scitos/view/ScitosIcon.java @@ -44,9 +44,9 @@ public enum ScitosIcon { /** Icon: closed model group folder in the main view's project tree. */ FOLDER_CLOSED("/icons/eclipse/folder_closed.png"), /** Icon: model element in the main view's project tree. */ - MODEL_ELEMENT("/icons/fatcow/clipboard_invoice.png"), + CLIPBOARD("/icons/fatcow/clipboard_invoice.png"), /** Icon: model element in the main view's project tree. */ - MODEL_ELEMENT_ADD("/icons/eclipse/add_task.png"), + CLIPBOARD_ADD("/icons/eclipse/add_task.png"), /** Icon: new file entry in menu bar / tool bar. */ NEW_FILE("/icons/fatcow/page_white_add.png"), /** Icon: save file entry in menu bar / tool bar. */ @@ -81,10 +81,14 @@ public enum ScitosIcon { ADD("/icons/fatcow/add.png"), /** Icon: remove entry e.g. in category tree table. **/ DELETE("/icons/fatcow/cross.png"), - /** Icon: model entry e.g. in category tree table. **/ - CATEGORY("/icons/fatcow/clipboard_invoice.png"), /** Icon: attributes list. */ ATTRIBUTES_DISPLAY("/icons/fatcow/attributes_display.png"), + /** Icon: a 3x3 grid. */ + GRID("/icons/fatcow/grid.png"), + /** Icon: a tree structure with two sub nodes. */ + TREE("/icons/fatcow/node_tree.png"), + /** Icon: relational (tree) lines (as on the semantical analysis in HermeneutiX), in red. */ + RELATIONS("/icons/misc/relations_red.png"), /** Icon: horizontal rule below (text) block. */ HORIZONTAL_RULE("/icons/fatcow/horizontal_rule.png"); diff --git a/scitos.view/src/main/java/org/hmx/scitos/view/swing/MainView.java b/scitos.view/src/main/java/org/hmx/scitos/view/swing/MainView.java index 0bf5e43..a598361 100644 --- a/scitos.view/src/main/java/org/hmx/scitos/view/swing/MainView.java +++ b/scitos.view/src/main/java/org/hmx/scitos/view/swing/MainView.java @@ -965,7 +965,7 @@ private final class ScitosTreeNodeRenderer extends DefaultTreeCellRenderer { /** Icon to display for main model group node in collapsed state. */ private final Icon multiModelGroupClosedIcon = ScitosIcon.FOLDER_CLOSED.create(); /** Icon to display for model element. */ - private final Icon modelIcon = ScitosIcon.MODEL_ELEMENT.create(); + private final Icon modelIcon = ScitosIcon.CLIPBOARD.create(); /** Main constructor, initializes look and feel coloring associated with text panes (instead of trees). */ ScitosTreeNodeRenderer() { diff --git a/scitos.view/src/main/java/org/hmx/scitos/view/swing/ScitosClient.java b/scitos.view/src/main/java/org/hmx/scitos/view/swing/ScitosClient.java index 1574547..23cae49 100644 --- a/scitos.view/src/main/java/org/hmx/scitos/view/swing/ScitosClient.java +++ b/scitos.view/src/main/java/org/hmx/scitos/view/swing/ScitosClient.java @@ -649,18 +649,18 @@ public void setViewMenuItems(final Collection menuItems) { private void setViewSpecificMenuItems(final JMenu targetMenu, final int fixedLeadingItemCount, final Collection menuItems) { if (targetMenu.getMenuComponentCount() > fixedLeadingItemCount) { // remove old view specific edit menu items - final List oldEditMenuItems = Arrays.asList(targetMenu.getMenuComponents()); - for (final Component oldEditMenuItem : oldEditMenuItems.subList(fixedLeadingItemCount, oldEditMenuItems.size())) { - targetMenu.remove(oldEditMenuItem); + final List oldMenuItems = Arrays.asList(targetMenu.getMenuComponents()); + for (final Component oldMenuItem : oldMenuItems.subList(fixedLeadingItemCount, oldMenuItems.size())) { + targetMenu.remove(oldMenuItem); } } if (!menuItems.isEmpty()) { targetMenu.addSeparator(); - for (final JMenuItem newEditMenuItem : menuItems) { - if (newEditMenuItem == null) { + for (final JMenuItem newMenuItem : menuItems) { + if (newMenuItem == null) { targetMenu.addSeparator(); } else { - targetMenu.add(newEditMenuItem); + targetMenu.add(newMenuItem); } } } @@ -748,7 +748,7 @@ void saveAs() { /** * Determine the currently active project - the one to be saved - and update the current list of open tabs in order to allow them to be saved as * part of project. - * + * * @return the currently active project */ private IViewProject prepareForSaving() { diff --git a/scitos.view/src/main/java/org/hmx/scitos/view/swing/util/table/TreeTable.java b/scitos.view/src/main/java/org/hmx/scitos/view/swing/util/table/TreeTable.java index 6736c92..20c613a 100644 --- a/scitos.view/src/main/java/org/hmx/scitos/view/swing/util/table/TreeTable.java +++ b/scitos.view/src/main/java/org/hmx/scitos/view/swing/util/table/TreeTable.java @@ -50,9 +50,8 @@ public class TreeTable extends JXTreeTable { /** * Constructor. - * - * @param treeModel - * model for this JXTreeTable instance + * + * @param treeModel model for this JXTreeTable instance */ public TreeTable(final TreeTableModel treeModel) { this.setAutoCreateColumnsFromModel(false); @@ -60,13 +59,13 @@ public TreeTable(final TreeTableModel treeModel) { this.setRootVisible(false); this.setOpenIcon(ScitosIcon.FOLDER_OPEN.create()); this.setClosedIcon(ScitosIcon.FOLDER_OPEN.create()); - this.setLeafIcon(ScitosIcon.CATEGORY.create()); + this.setLeafIcon(ScitosIcon.CLIPBOARD.create()); this.setAutoStartEditOnKeyStroke(false); } /** * Ensure that the non-leaf nodes are never collapsed. - * + * * @return this TreeTable instance (for chaining) */ public TreeTable setAlwaysExpanded() { @@ -112,7 +111,7 @@ public void treeStructureChanged(final TreeModelEvent event) { /** * Wrap the this tree table in a borderless {@link JScrollPane}. - * + * * @return the created scroll pane */ public JScrollPane createScrollableWrapper() { @@ -124,10 +123,8 @@ public JScrollPane createScrollableWrapper() { /** * Add a single column to this tree table with the given attributes. * - * @param minWidth - * the minimum column width - * @param maxWidth - * the maximum column width + * @param minWidth the minimum column width + * @param maxWidth the maximum column width * @return the created table column * @see #addColumn(int, int, TableCellRenderer, TableCellEditor) */ @@ -138,14 +135,10 @@ public TableColumnExt addColumn(final int minWidth, final int maxWidth) { /** * Add a single column to this tree table with the given attributes. * - * @param minWidth - * the minimum column width - * @param maxWidth - * the maximum column width - * @param renderer - * the (optional) custom renderer to apply for this column (when not in editable state) - * @param editor - * the (optional) custom editor to apply for this column + * @param minWidth the minimum column width + * @param maxWidth the maximum column width + * @param renderer the (optional) custom renderer to apply for this column (when not in editable state) + * @param editor the (optional) custom editor to apply for this column * @return the created table column */ public TableColumnExt addColumn(final int minWidth, final int maxWidth, final TableCellRenderer renderer, final TableCellEditor editor) { @@ -166,10 +159,8 @@ public TableColumnExt addColumn(final int minWidth, final int maxWidth, final Ta * Add a single column to this tree table with the given attributes and the default table cell renderer (with the addition of a tooltip that * displays the cell's value). * - * @param minWidth - * the minimum column width - * @param maxWidth - * the maximum column width + * @param minWidth the minimum column width + * @param maxWidth the maximum column width * @return the created table column */ public TableColumnExt addColumnWithToolTip(final int minWidth, final int maxWidth) { @@ -196,10 +187,8 @@ public JComponent getTableCellRendererComponent(final JTable table, final Object /** * Add a single column to this tree table displaying an icon-only button. * - * @param icon - * the button's icon to display - * @param action - * the button's associated on-click action + * @param icon the button's icon to display + * @param action the button's associated on-click action * @return the created table column */ public TableColumnExt addButtonColumn(final ScitosIcon icon, final Action action) { @@ -209,11 +198,9 @@ public TableColumnExt addButtonColumn(final ScitosIcon icon, final Action action /** * Set the handled table's row height according to the component rendered in the designated column for the provided value. - * - * @param referenceColumn - * column that determines the desired row height - * @param referenceValue - * the value to use when calculating the preferred row height + * + * @param referenceColumn column that determines the desired row height + * @param referenceValue the value to use when calculating the preferred row height */ public void applyRowHeight(final TableColumnExt referenceColumn, final Object referenceValue) { final TableCellRenderer renderer = referenceColumn.getCellRenderer(); @@ -224,7 +211,7 @@ public void applyRowHeight(final TableColumnExt referenceColumn, final Object re /** * Determine the tree path to the currently selected row, if there is one. - * + * * @return selected row's tree path */ public TreePath getSelectedPath() { @@ -233,9 +220,8 @@ public TreePath getSelectedPath() { /** * Set the selected tree path. - * - * @param path - * designated row's tree path to select + * + * @param path designated row's tree path to select */ public void setSelectedPath(final TreePath path) { this.getTreeSelectionModel().setSelectionPath(path); @@ -243,9 +229,8 @@ public void setSelectedPath(final TreePath path) { /** * Determine those paths under the same parent that are currently expanded. - * - * @param parentPath - * path to collect the expanded children for + * + * @param parentPath path to collect the expanded children for * @return the child paths that are expanded * @see #isExpanded(TreePath) */ @@ -264,9 +249,8 @@ public List getExpandedChildren(final TreePath parentPath) { /** * Expand the nodes at the given path in the tree table. - * - * @param targetPaths - * paths to the nodes to expand + * + * @param targetPaths paths to the nodes to expand * @see #expandPath(TreePath) */ public void expandPaths(final List targetPaths) { diff --git a/scitos.view/src/main/resources/icons/fatcow/grid.png b/scitos.view/src/main/resources/icons/fatcow/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..39448adf5561dcc36011676a20b69aba5d27e926 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`m7Xq+Ar*0JgANKd7;rSN3labH znuG5FN8Q{LGXqvx`u$qCZRcs#Cl@awvnc39Ix zFzpSSv-h?8j6RBc9AE7^XS_nVv#Q{Lu$5sB*Oy{p&6OoNN*{l3UY@Nxi+7IGZzai1 c*E`zd&R!_?cp7#=2YwwY+zSU0quc1OcSh8WzQeAMpC? zZ)=Uru5CEk-wX19VWDB#Sxqa5ot-J(OGJ3`_B&>$#_;9WKhzgq;_Pq=`9c8$nG6Z7 zSRpew%p&WdjAEUPqmHC|apl%izUj!m?eK&^v3P@H#J3xwrgMe{Lz*aDemsq>f9_y% zViHs;6e%UKr5xeef;@Q1aybGIYZ_=O0k5M2!QwYO|G2`19p2M}b0d9REXR*76hg!X zZsYsbOJMG11rL7qVCMWNKCi6d-ogu9I<_09&rDDsgQV3QC!0MLMKFjAd?>AvyHLPd z_y+mPV^|zLu#!LIz)voqH*zqE|Pi6M**rE!1h6CfmI&LRv$ z)a!NBYPDp97+0@N^V*z$hs%{muo&;}1A&AgHbkjZGMk0f%0{E{s$4D)D5YGKC{CO) n&TWtYznazBu@tczo5SjV(KSdKzbuJ@VVD_UC<6{NG_fI~0ue<-1QkJoA_k0xBC#Thg@9ne9*`iQ#9$Or zQF$}6R&?d%y_c8YA7_1QpS|}zXYYO1x&V;8{kgn!SPFnNo`4_X6{c}T{8k*B#$jdxfFg<9uYy1K45IaYvHg`_dOZM)Sy63ve6hvv z1)yUy0P^?0*fb9UASvow`@mQCp^4`uNg&9uGcn1|&Nk+9SjOUl{-OWr@Hh0;_l(8q z{wNRKos+;6rV8ldy0Owz(}jF`W(JeRp&R{qi2rfmU!TJ;gp(Kmm5I1s5m_f-n#TRsj}B0%?E`vOzxB2#P=n*a3EfYETOrKoe*ICqM@{4K9Go;5xVgZi5G4 z1dM~{UdP6d+Yd3o?MrAqM0Kc|iV92owdyL5UC#5<>aVCa44|hpM4E zs0sQWIt5*Tu0n&*J!lk~f_{hI!w5`*sjxDv4V%CW*ah~3!{C*0BD@;TgA3v9a1~q+ zAA{TB3-ERLHar49hi4Ih5D^-ph8Q6X#0?2VqLBoIkE}zAkxHZUgRb+f=nat zP#6>iMMoK->`~sRLq)(kHo*Vn{;LcG6+edD1=7D>9j^O?D{Qg|tCDK{ym)H7&wDr6*;uGTJg8GHjVbnL{!cWyUB7MT6o-VNo_w8Yq`2<5Ub)hw4L3rj}5@qxMs0 zWMyP6Wy582WNT#4$d1qunl{acmP#w5ouJ*Jy_Zv#bCKi7ZIf$}8d zZdVy&)LYdbX%I9R8VMQ|8r>Q*nyQ)sn)#Z|n)kKvS`4iu ztvy=3T65Yu+7a4Yv^%sXb>ww?bn(=Yu(!=O6^iuTp>)p_Y^{w=i z^lS773}6Fm1Fpe-gF!>Ip{*g$u-szvGhed;vo5pW&GpS$<~8QGEXWp~7V9lKEnZq0SaK{6Sl+dwSOr*Z zvFf(^Xl-N7w{EeXveC4Ov)N}e%%C!Y7^RFWwrE>d+x51mZQt2h+X?JW*!^a2WS?Sx z)P8cQ&Qi|OhNWW;>JChYI)@QQx?`Nj^#uJBl~d&PK+RZLOLos~K(b5>qmrMN0})tOkySZ3_W zICNY@+|jrX%s^&6b2i>5eqa0y%Z;^%^_=a@u3%4b9605ii3Ep)@`TAmhs0fpQ%O!q zl}XcFH*PieWwLj2ZSq`7V9Mc?h17`D)-+sNT-qs~3@?S(ldh7UlRlVXkWrK|vf6I- z?$tAVKYn8-l({mqQ$Q8{O!WzMg`0(=S&msXS#Pt$vrpzo=kRj+a`kh!z=6$;c zwT88(J6|n-WB%w`m$h~4pmp)YIh_ z3ETV2tjiAU!0h1dxU-n=E9e!)6|Z;4?!H=SSy{V>ut&IOq{_dl zbFb#!9eY1iCsp6Bajj|Hr?hX|zPbJE{X++w546-O*Ot`2Kgd0Jx6Z4syT zu9enWavU5N9)I?I-1m1*_?_rJ$vD~agVqoG+9++s?NEDe`%Fht$4F;X=in*dQ{7$m zU2Q)a|9JSc+Uc4zvS-T963!N$T{xF_ZuWe}`RNOZ7sk3{yB}PPym+f8xTpV;-=!;; zJuhGEb?H5K#o@~7t9DmUU1MD9xNd#Dz0azz?I)|B+WM{g+Xrk0I&awC=o(x)cy`EX z=)z6+o0o6-+`4{y+3mqQ%kSJBju{@g%f35#FZJHb`&swrA8dGtepviS>QUumrN{L@ z>;2q1Vm)$Z)P1z?N$8UYW2~{~zhwUMVZ87u`Dx{Z>O|9|`Q+&->FRy-Sjp7DHs zy69KwU-!MxeeuI@&cF4|M9z%AfP?@5 z`Tzg`fam}Kbua(`>RI+y?e7jT@qQ9J+u076MbK~y-)V_+C)z{tSBz;N2Y_&+(C zO)s2fWTLv0P8%5iC&fh+yMST?Scvr&%>t2y)My)gfyhW~fYC1{(j5Q*m1+`3#^-r> P00000NkvXXu0mjfY+q$5 literal 0 HcmV?d00001