From 5fa8c46efcabfb50f5f400c1c2ebcbe63add41e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Fri, 5 Nov 2021 15:10:23 +0100 Subject: [PATCH] upgrade to new data structure --- .../java/de/marhali/easyi18n/DataBus.java | 2 +- .../marhali/easyi18n/action/ReloadAction.java | 4 +- .../de/marhali/easyi18n/dialog/AddDialog.java | 16 +- .../marhali/easyi18n/dialog/EditDialog.java | 29 +-- .../easyi18n/dialog/SettingsDialog.java | 4 +- .../marhali/easyi18n/editor/KeyAnnotator.java | 2 - .../editor/KeyCompletionProvider.java | 2 - .../marhali/easyi18n/editor/KeyReference.java | 3 - .../GenericKeyReferenceContributor.java | 1 - .../kotlin/KotlinKeyReferenceContributor.java | 1 - .../de/marhali/easyi18n/io/TranslatorIO.java | 2 - .../io/implementation/JsonTranslatorIO.java | 4 - .../ModularizedJsonTranslatorIO.java | 4 - .../PropertiesTranslatorIO.java | 4 - .../marhali/easyi18n/model/BusListener.java | 29 --- .../easyi18n/model/DataSynchronizer.java | 20 -- .../model/LegacyKeyedTranslation.java | 43 ----- .../model/LegacyTranslationUpdate.java | 47 ----- .../marhali/easyi18n/model/LocalizedNode.java | 78 -------- .../easyi18n/model/TranslationCreate.java | 4 +- .../easyi18n/model/TranslationDelete.java | 4 +- .../marhali/easyi18n/model/Translations.java | 109 ----------- .../easyi18n/model/bus/BusListener.java | 8 + .../easyi18n/model/bus/FocusKeyListener.java | 15 ++ .../model/bus/SearchQueryListener.java | 16 ++ .../model/bus/UpdateDataListener.java | 16 ++ .../model/table/TableModelTranslator.java | 5 - .../model/tree/TreeModelTranslator.java | 3 - .../easyi18n/service/LegacyDataStore.java | 174 ------------------ .../service/TranslatorToolWindowFactory.java | 13 +- .../de/marhali/easyi18n/tabs/TableView.java | 60 +++--- .../de/marhali/easyi18n/tabs/TreeView.java | 49 ++--- .../tabs/mapper/TableModelMapper.java | 112 +++++++++++ .../easyi18n/tabs/mapper/TreeModelMapper.java | 104 +++++++++++ .../java/de/marhali/easyi18n/util/IOUtil.java | 72 -------- .../de/marhali/easyi18n/util/JsonUtil.java | 97 ---------- .../de/marhali/easyi18n/util/MapUtil.java | 3 +- .../easyi18n/util/SortedProperties.java | 1 + .../easyi18n/util/TranslationsUtil.java | 48 ----- .../de/marhali/easyi18n/util/TreeUtil.java | 4 +- 40 files changed, 371 insertions(+), 841 deletions(-) delete mode 100644 src/main/java/de/marhali/easyi18n/model/BusListener.java delete mode 100644 src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java delete mode 100644 src/main/java/de/marhali/easyi18n/model/LegacyKeyedTranslation.java delete mode 100644 src/main/java/de/marhali/easyi18n/model/LegacyTranslationUpdate.java delete mode 100644 src/main/java/de/marhali/easyi18n/model/LocalizedNode.java delete mode 100644 src/main/java/de/marhali/easyi18n/model/Translations.java create mode 100644 src/main/java/de/marhali/easyi18n/model/bus/BusListener.java create mode 100644 src/main/java/de/marhali/easyi18n/model/bus/FocusKeyListener.java create mode 100644 src/main/java/de/marhali/easyi18n/model/bus/SearchQueryListener.java create mode 100644 src/main/java/de/marhali/easyi18n/model/bus/UpdateDataListener.java delete mode 100644 src/main/java/de/marhali/easyi18n/service/LegacyDataStore.java create mode 100644 src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java create mode 100644 src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java delete mode 100644 src/main/java/de/marhali/easyi18n/util/IOUtil.java delete mode 100644 src/main/java/de/marhali/easyi18n/util/JsonUtil.java delete mode 100644 src/main/java/de/marhali/easyi18n/util/TranslationsUtil.java diff --git a/src/main/java/de/marhali/easyi18n/DataBus.java b/src/main/java/de/marhali/easyi18n/DataBus.java index 56dba9b..101a8fd 100644 --- a/src/main/java/de/marhali/easyi18n/DataBus.java +++ b/src/main/java/de/marhali/easyi18n/DataBus.java @@ -1,6 +1,6 @@ package de.marhali.easyi18n; -import de.marhali.easyi18n.model.BusListener; +import de.marhali.easyi18n.model.bus.BusListener; import de.marhali.easyi18n.model.TranslationData; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/action/ReloadAction.java b/src/main/java/de/marhali/easyi18n/action/ReloadAction.java index 1f380fc..3e24e04 100644 --- a/src/main/java/de/marhali/easyi18n/action/ReloadAction.java +++ b/src/main/java/de/marhali/easyi18n/action/ReloadAction.java @@ -4,7 +4,7 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import de.marhali.easyi18n.service.LegacyDataStore; +import de.marhali.easyi18n.InstanceManager; import org.jetbrains.annotations.NotNull; @@ -23,6 +23,6 @@ public class ReloadAction extends AnAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { - LegacyDataStore.getInstance(e.getProject()).reloadFromDisk(); + InstanceManager.get(e.getProject()).store().loadFromPersistenceLayer((success) -> {}); } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java b/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java index 7466206..7702fba 100644 --- a/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java +++ b/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java @@ -7,8 +7,9 @@ import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBTextField; -import de.marhali.easyi18n.service.LegacyDataStore; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; +import de.marhali.easyi18n.InstanceManager; +import de.marhali.easyi18n.model.KeyedTranslation; +import de.marhali.easyi18n.model.Translation; import de.marhali.easyi18n.model.TranslationCreate; import javax.swing.*; @@ -48,16 +49,16 @@ public class AddDialog { } private void saveTranslation() { - Map messages = new HashMap<>(); + Translation translation = new Translation(); valueTextFields.forEach((k, v) -> { if(!v.getText().isEmpty()) { - messages.put(k, v.getText()); + translation.put(k, v.getText()); } }); - TranslationCreate creation = new TranslationCreate(new LegacyKeyedTranslation(keyTextField.getText(), messages)); - LegacyDataStore.getInstance(project).processUpdate(creation); + TranslationCreate creation = new TranslationCreate(new KeyedTranslation(keyTextField.getText(), translation)); + InstanceManager.get(project).processUpdate(creation); } private DialogBuilder prepare() { @@ -75,7 +76,8 @@ public class AddDialog { JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2)); valueTextFields = new HashMap<>(); - for(String locale : LegacyDataStore.getInstance(project).getTranslations().getLocales()) { + + for(String locale : InstanceManager.get(project).store().getData().getLocales()) { JBLabel localeLabel = new JBLabel(locale); JBTextField localeText = new JBTextField(); localeLabel.setLabelFor(localeText); diff --git a/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java b/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java index 33023c1..7e788bf 100644 --- a/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java +++ b/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java @@ -6,11 +6,12 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBTextField; -import de.marhali.easyi18n.service.LegacyDataStore; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; +import de.marhali.easyi18n.InstanceManager; +import de.marhali.easyi18n.model.KeyedTranslation; +import de.marhali.easyi18n.model.Translation; import de.marhali.easyi18n.model.TranslationDelete; -import de.marhali.easyi18n.model.LegacyTranslationUpdate; import de.marhali.easyi18n.dialog.descriptor.DeleteActionDescriptor; +import de.marhali.easyi18n.model.TranslationUpdate; import javax.swing.*; import javax.swing.border.EtchedBorder; @@ -26,12 +27,12 @@ import java.util.ResourceBundle; public class EditDialog { private final Project project; - private final LegacyKeyedTranslation origin; + private final KeyedTranslation origin; private JBTextField keyTextField; private Map valueTextFields; - public EditDialog(Project project, LegacyKeyedTranslation origin) { + public EditDialog(Project project, KeyedTranslation origin) { this.project = project; this.origin = origin; } @@ -40,23 +41,22 @@ public class EditDialog { int code = prepare().show(); if(code == DialogWrapper.OK_EXIT_CODE) { // Edit - LegacyDataStore.getInstance(project).processUpdate(new LegacyTranslationUpdate(origin, getChanges())); - + InstanceManager.get(project).processUpdate(new TranslationUpdate(origin, getChanges())); } else if(code == DeleteActionDescriptor.EXIT_CODE) { // Delete - LegacyDataStore.getInstance(project).processUpdate(new TranslationDelete(origin)); + InstanceManager.get(project).processUpdate(new TranslationDelete(origin)); } } - private LegacyKeyedTranslation getChanges() { - Map messages = new HashMap<>(); + private KeyedTranslation getChanges() { + Translation translation = new Translation(); valueTextFields.forEach((k, v) -> { if(!v.getText().isEmpty()) { - messages.put(k, v.getText()); + translation.put(k, v.getText()); } }); - return new LegacyKeyedTranslation(keyTextField.getText(), messages); + return new KeyedTranslation(keyTextField.getText(), translation); } private DialogBuilder prepare() { @@ -74,9 +74,10 @@ public class EditDialog { JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2)); valueTextFields = new HashMap<>(); - for(String locale : LegacyDataStore.getInstance(project).getTranslations().getLocales()) { + + for(String locale : InstanceManager.get(project).store().getData().getLocales()) { JBLabel localeLabel = new JBLabel(locale); - JBTextField localeText = new JBTextField(this.origin.getTranslations().get(locale)); + JBTextField localeText = new JBTextField(this.origin.getTranslation().get(locale)); localeLabel.setLabelFor(localeText); valuePanel.add(localeLabel); diff --git a/src/main/java/de/marhali/easyi18n/dialog/SettingsDialog.java b/src/main/java/de/marhali/easyi18n/dialog/SettingsDialog.java index bf388d1..e0dd7eb 100644 --- a/src/main/java/de/marhali/easyi18n/dialog/SettingsDialog.java +++ b/src/main/java/de/marhali/easyi18n/dialog/SettingsDialog.java @@ -9,9 +9,9 @@ import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBTextField; +import de.marhali.easyi18n.InstanceManager; import de.marhali.easyi18n.model.SettingsState; import de.marhali.easyi18n.service.SettingsService; -import de.marhali.easyi18n.service.LegacyDataStore; import javax.swing.*; import java.awt.*; @@ -50,7 +50,7 @@ public class SettingsDialog { state.setCodeAssistance(codeAssistanceCheckbox.isSelected()); // Reload instance - LegacyDataStore.getInstance(project).reloadFromDisk(); + InstanceManager.get(project).store().loadFromPersistenceLayer((success) -> {}); } } diff --git a/src/main/java/de/marhali/easyi18n/editor/KeyAnnotator.java b/src/main/java/de/marhali/easyi18n/editor/KeyAnnotator.java index f90e753..6b9f91d 100644 --- a/src/main/java/de/marhali/easyi18n/editor/KeyAnnotator.java +++ b/src/main/java/de/marhali/easyi18n/editor/KeyAnnotator.java @@ -4,8 +4,6 @@ import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.project.Project; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.service.LegacyDataStore; import de.marhali.easyi18n.service.SettingsService; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/editor/KeyCompletionProvider.java b/src/main/java/de/marhali/easyi18n/editor/KeyCompletionProvider.java index 7166765..79e1e8e 100644 --- a/src/main/java/de/marhali/easyi18n/editor/KeyCompletionProvider.java +++ b/src/main/java/de/marhali/easyi18n/editor/KeyCompletionProvider.java @@ -5,9 +5,7 @@ import com.intellij.codeInsight.lookup.*; import com.intellij.icons.AllIcons; import com.intellij.openapi.project.*; import com.intellij.util.*; -import de.marhali.easyi18n.model.*; import de.marhali.easyi18n.service.*; -import de.marhali.easyi18n.util.TranslationsUtil; import org.jetbrains.annotations.*; import java.util.*; diff --git a/src/main/java/de/marhali/easyi18n/editor/KeyReference.java b/src/main/java/de/marhali/easyi18n/editor/KeyReference.java index e319075..960f680 100644 --- a/src/main/java/de/marhali/easyi18n/editor/KeyReference.java +++ b/src/main/java/de/marhali/easyi18n/editor/KeyReference.java @@ -6,9 +6,6 @@ import com.intellij.psi.impl.FakePsiElement; import de.marhali.easyi18n.dialog.AddDialog; import de.marhali.easyi18n.dialog.EditDialog; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.service.LegacyDataStore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/de/marhali/easyi18n/editor/generic/GenericKeyReferenceContributor.java b/src/main/java/de/marhali/easyi18n/editor/generic/GenericKeyReferenceContributor.java index 377ce8a..4debdc3 100644 --- a/src/main/java/de/marhali/easyi18n/editor/generic/GenericKeyReferenceContributor.java +++ b/src/main/java/de/marhali/easyi18n/editor/generic/GenericKeyReferenceContributor.java @@ -5,7 +5,6 @@ import com.intellij.psi.*; import com.intellij.util.ProcessingContext; import de.marhali.easyi18n.editor.KeyReference; -import de.marhali.easyi18n.service.LegacyDataStore; import de.marhali.easyi18n.service.SettingsService; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/editor/kotlin/KotlinKeyReferenceContributor.java b/src/main/java/de/marhali/easyi18n/editor/kotlin/KotlinKeyReferenceContributor.java index 3a18c8f..1ae339e 100644 --- a/src/main/java/de/marhali/easyi18n/editor/kotlin/KotlinKeyReferenceContributor.java +++ b/src/main/java/de/marhali/easyi18n/editor/kotlin/KotlinKeyReferenceContributor.java @@ -6,7 +6,6 @@ import com.intellij.psi.*; import com.intellij.util.ProcessingContext; import de.marhali.easyi18n.editor.KeyReference; -import de.marhali.easyi18n.service.LegacyDataStore; import de.marhali.easyi18n.service.SettingsService; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/io/TranslatorIO.java b/src/main/java/de/marhali/easyi18n/io/TranslatorIO.java index 1d18872..aee3088 100644 --- a/src/main/java/de/marhali/easyi18n/io/TranslatorIO.java +++ b/src/main/java/de/marhali/easyi18n/io/TranslatorIO.java @@ -2,8 +2,6 @@ package de.marhali.easyi18n.io; import com.intellij.openapi.project.Project; -import de.marhali.easyi18n.model.Translations; - import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; diff --git a/src/main/java/de/marhali/easyi18n/io/implementation/JsonTranslatorIO.java b/src/main/java/de/marhali/easyi18n/io/implementation/JsonTranslatorIO.java index 1efbd0e..9bc18e3 100644 --- a/src/main/java/de/marhali/easyi18n/io/implementation/JsonTranslatorIO.java +++ b/src/main/java/de/marhali/easyi18n/io/implementation/JsonTranslatorIO.java @@ -7,10 +7,6 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import de.marhali.easyi18n.io.TranslatorIO; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.util.IOUtil; -import de.marhali.easyi18n.util.JsonUtil; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/io/implementation/ModularizedJsonTranslatorIO.java b/src/main/java/de/marhali/easyi18n/io/implementation/ModularizedJsonTranslatorIO.java index 0cc70d9..c49cd97 100644 --- a/src/main/java/de/marhali/easyi18n/io/implementation/ModularizedJsonTranslatorIO.java +++ b/src/main/java/de/marhali/easyi18n/io/implementation/ModularizedJsonTranslatorIO.java @@ -10,10 +10,6 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import de.marhali.easyi18n.io.TranslatorIO; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.util.IOUtil; -import de.marhali.easyi18n.util.JsonUtil; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/io/implementation/PropertiesTranslatorIO.java b/src/main/java/de/marhali/easyi18n/io/implementation/PropertiesTranslatorIO.java index 458c49a..ec25a04 100644 --- a/src/main/java/de/marhali/easyi18n/io/implementation/PropertiesTranslatorIO.java +++ b/src/main/java/de/marhali/easyi18n/io/implementation/PropertiesTranslatorIO.java @@ -6,12 +6,8 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import de.marhali.easyi18n.io.TranslatorIO; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.util.IOUtil; import de.marhali.easyi18n.util.SortedProperties; import de.marhali.easyi18n.util.StringUtil; -import de.marhali.easyi18n.util.TranslationsUtil; import org.apache.commons.lang.StringEscapeUtils; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/model/BusListener.java b/src/main/java/de/marhali/easyi18n/model/BusListener.java deleted file mode 100644 index 752dde0..0000000 --- a/src/main/java/de/marhali/easyi18n/model/BusListener.java +++ /dev/null @@ -1,29 +0,0 @@ -package de.marhali.easyi18n.model; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Interface for communication of changes for participants of the data bus. - * @author marhali - */ -public interface BusListener { - /** - * Update the translations based on the supplied data. - * @param data Updated translations - */ - void onUpdateData(@NotNull TranslationData data); - - /** - * Move the specified translation key (full-key) into focus. - * @param key Absolute translation key - */ - void onFocusKey(@Nullable String key); - - /** - * Filter the displayed data according to the search query. Supply 'null' to return to the normal state. - * The keys and the content itself should be considered. - * @param query Filter key or content - */ - void onSearchQuery(@Nullable String query); -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java b/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java deleted file mode 100644 index 6604520..0000000 --- a/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.marhali.easyi18n.model; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Interface to communicate data changes between data store and ui components. - * @author marhali - */ -@Deprecated -public interface DataSynchronizer { - - /** - * Propagates data changes to implementation classes. - * @param translations Updated translations model - * @param searchQuery Can be used to filter visible data. Like a search function for the full key path - * @param scrollToKey Focus specific translation. Can be null to disable this function - */ - void synchronize(@NotNull Translations translations, @Nullable String searchQuery, @Nullable String scrollToKey); -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/LegacyKeyedTranslation.java b/src/main/java/de/marhali/easyi18n/model/LegacyKeyedTranslation.java deleted file mode 100644 index 1ef1e34..0000000 --- a/src/main/java/de/marhali/easyi18n/model/LegacyKeyedTranslation.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.marhali.easyi18n.model; - -import java.util.Map; - -/** - * Translated messages for a dedicated key. - * @author marhali - */ -@Deprecated // Might be deprecated -public class LegacyKeyedTranslation { - - private String key; - private Map translations; - - public LegacyKeyedTranslation(String key, Map translations) { - this.key = key; - this.translations = translations; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Map getTranslations() { - return translations; - } - - public void setTranslations(Map translations) { - this.translations = translations; - } - - @Override - public String toString() { - return "KeyedTranslation{" + - "key='" + key + '\'' + - ", translations=" + translations + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/LegacyTranslationUpdate.java b/src/main/java/de/marhali/easyi18n/model/LegacyTranslationUpdate.java deleted file mode 100644 index 2a73c01..0000000 --- a/src/main/java/de/marhali/easyi18n/model/LegacyTranslationUpdate.java +++ /dev/null @@ -1,47 +0,0 @@ -package de.marhali.easyi18n.model; - -import org.jetbrains.annotations.Nullable; - -/** - * Represents an update for a translated I18n-Key. Supports key creation, manipulation and deletion. - * @author marhali - */ -@Deprecated -public class LegacyTranslationUpdate { - - private final @Nullable LegacyKeyedTranslation origin; - private final @Nullable LegacyKeyedTranslation change; - - public LegacyTranslationUpdate(@Nullable LegacyKeyedTranslation origin, @Nullable LegacyKeyedTranslation change) { - this.origin = origin; - this.change = change; - } - - public LegacyKeyedTranslation getOrigin() { - return origin; - } - - public LegacyKeyedTranslation getChange() { - return change; - } - - public boolean isCreation() { - return origin == null; - } - - public boolean isDeletion() { - return change == null; - } - - public boolean isKeyChange() { - return origin != null && change != null && !origin.getKey().equals(change.getKey()); - } - - @Override - public String toString() { - return "TranslationUpdate{" + - "origin=" + origin + - ", change=" + change + - '}'; - } -} diff --git a/src/main/java/de/marhali/easyi18n/model/LocalizedNode.java b/src/main/java/de/marhali/easyi18n/model/LocalizedNode.java deleted file mode 100644 index 85376f1..0000000 --- a/src/main/java/de/marhali/easyi18n/model/LocalizedNode.java +++ /dev/null @@ -1,78 +0,0 @@ -package de.marhali.easyi18n.model; - -import de.marhali.easyi18n.util.MapUtil; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * Represents structured tree view for translated messages. - * @author marhali - */ -@Deprecated -public class LocalizedNode { - - public static final String ROOT_KEY = "root"; - - @NotNull - private final String key; - - @NotNull - private TreeMap children; - - @NotNull - private Map value; - - public LocalizedNode(@NotNull String key, @NotNull List children) { - this.key = key; - this.children = MapUtil.convertToTreeMap(children); - this.value = new HashMap<>(); - } - - public LocalizedNode(@NotNull String key, @NotNull Map value) { - this.key = key; - this.children = new TreeMap<>(); - this.value = value; - } - - public @NotNull String getKey() { - return key; - } - - public boolean isLeaf() { - return children.isEmpty(); - } - - public @NotNull Collection getChildren() { - return children.values(); - } - - public @Nullable LocalizedNode getChildren(@NotNull String key) { - return children.get(key); - } - - public void setChildren(@NotNull LocalizedNode... children) { - this.value.clear(); - this.children = MapUtil.convertToTreeMap(Arrays.asList(children)); - } - - public void addChildren(@NotNull LocalizedNode... children) { - this.value.clear(); - Arrays.stream(children).forEach(e -> this.children.put(e.getKey(), e)); - } - - public void removeChildren(@NotNull String key) { - this.children.remove(key); - } - - public @NotNull Map getValue() { - return value; - } - - public void setValue(@NotNull Map value) { - this.children.clear(); - this.value = value; - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/TranslationCreate.java b/src/main/java/de/marhali/easyi18n/model/TranslationCreate.java index 0d6d2aa..9c955a9 100644 --- a/src/main/java/de/marhali/easyi18n/model/TranslationCreate.java +++ b/src/main/java/de/marhali/easyi18n/model/TranslationCreate.java @@ -6,8 +6,8 @@ import org.jetbrains.annotations.NotNull; * Represents update request to create a new translation. * @author marhali */ -public class TranslationCreate extends LegacyTranslationUpdate { - public TranslationCreate(@NotNull LegacyKeyedTranslation translation) { +public class TranslationCreate extends TranslationUpdate { + public TranslationCreate(@NotNull KeyedTranslation translation) { super(null, translation); } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/TranslationDelete.java b/src/main/java/de/marhali/easyi18n/model/TranslationDelete.java index 14d7ee0..763cb16 100644 --- a/src/main/java/de/marhali/easyi18n/model/TranslationDelete.java +++ b/src/main/java/de/marhali/easyi18n/model/TranslationDelete.java @@ -6,8 +6,8 @@ import org.jetbrains.annotations.NotNull; * Represents update request to delete a existing translation. * @author marhali */ -public class TranslationDelete extends LegacyTranslationUpdate { - public TranslationDelete(@NotNull LegacyKeyedTranslation translation) { +public class TranslationDelete extends TranslationUpdate { + public TranslationDelete(@NotNull KeyedTranslation translation) { super(translation, null); } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/Translations.java b/src/main/java/de/marhali/easyi18n/model/Translations.java deleted file mode 100644 index 8727507..0000000 --- a/src/main/java/de/marhali/easyi18n/model/Translations.java +++ /dev/null @@ -1,109 +0,0 @@ -package de.marhali.easyi18n.model; - -import de.marhali.easyi18n.util.TranslationsUtil; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents translation state instance. IO operations will be based on this file. - * @author marhali - */ -@Deprecated -public class Translations { - - public static Translations empty() { - return new Translations(new ArrayList<>(), new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); - } - - @NotNull - private final List locales; - - @NotNull - private final LocalizedNode nodes; - - /** - * Constructs a new translation state instance. - * @param locales List of all locales which are used for create / edit I18n-Key operations - * @param nodes Represents the translation state. Internally handled as a tree. See {@link LocalizedNode} - */ - public Translations(@NotNull List locales, @NotNull LocalizedNode nodes) { - this.locales = locales; - this.nodes = nodes; - } - - public @NotNull List getLocales() { - return locales; - } - - public @NotNull LocalizedNode getNodes() { - return nodes; - } - - public @Nullable LocalizedNode getNode(@NotNull String fullPath) { - List sections = TranslationsUtil.getSections(fullPath); - - LocalizedNode node = nodes; - - for(String section : sections) { - if(node == null) { - return null; - } - node = node.getChildren(section); - } - - return node; - } - - public @NotNull LocalizedNode getOrCreateNode(@NotNull String fullPath) { - List sections = TranslationsUtil.getSections(fullPath); - - LocalizedNode node = nodes; - - for(String section : sections) { - LocalizedNode subNode = node.getChildren(section); - - if(subNode == null) { - subNode = new LocalizedNode(section, new ArrayList<>()); - node.addChildren(subNode); - } - - node = subNode; - } - - return node; - } - - public @NotNull List getFullKeys() { - List keys = new ArrayList<>(); - - if(nodes.isLeaf()) { // Root has no children - return keys; - } - - for(LocalizedNode children : nodes.getChildren()) { - keys.addAll(getFullKeys("", children)); - } - - return keys; - } - - public @NotNull List getFullKeys(String parentFullPath, LocalizedNode localizedNode) { - List keys = new ArrayList<>(); - - if(localizedNode.isLeaf()) { - keys.add(parentFullPath + (parentFullPath.isEmpty() ? "" : ".") + localizedNode.getKey()); - return keys; - } - - for(LocalizedNode children : localizedNode.getChildren()) { - String childrenPath = parentFullPath + (parentFullPath.isEmpty() ? "" : ".") + localizedNode.getKey(); - keys.addAll(getFullKeys(childrenPath, children)); - } - - return keys; - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/bus/BusListener.java b/src/main/java/de/marhali/easyi18n/model/bus/BusListener.java new file mode 100644 index 0000000..76a7c17 --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/model/bus/BusListener.java @@ -0,0 +1,8 @@ +package de.marhali.easyi18n.model.bus; + +/** + * Interface for communication of changes for participants of the data bus. + * Every listener needs to be registered manually via {@link de.marhali.easyi18n.DataBus}. + * @author marhali + */ +public interface BusListener extends UpdateDataListener, FocusKeyListener, SearchQueryListener {} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/bus/FocusKeyListener.java b/src/main/java/de/marhali/easyi18n/model/bus/FocusKeyListener.java new file mode 100644 index 0000000..ce3069f --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/model/bus/FocusKeyListener.java @@ -0,0 +1,15 @@ +package de.marhali.easyi18n.model.bus; + +import org.jetbrains.annotations.Nullable; + +/** + * Single event listener. + * @author marhali + */ +public interface FocusKeyListener { + /** + * Move the specified translation key (full-key) into focus. + * @param key Absolute translation key + */ + void onFocusKey(@Nullable String key); +} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/bus/SearchQueryListener.java b/src/main/java/de/marhali/easyi18n/model/bus/SearchQueryListener.java new file mode 100644 index 0000000..293f3ce --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/model/bus/SearchQueryListener.java @@ -0,0 +1,16 @@ +package de.marhali.easyi18n.model.bus; + +import org.jetbrains.annotations.Nullable; + +/** + * Single event listener. + * @author marhali + */ +public interface SearchQueryListener { + /** + * Filter the displayed data according to the search query. Supply 'null' to return to the normal state. + * The keys and the content itself should be considered. + * @param query Filter key or content + */ + void onSearchQuery(@Nullable String query); +} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/bus/UpdateDataListener.java b/src/main/java/de/marhali/easyi18n/model/bus/UpdateDataListener.java new file mode 100644 index 0000000..d6c9cb2 --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/model/bus/UpdateDataListener.java @@ -0,0 +1,16 @@ +package de.marhali.easyi18n.model.bus; + +import de.marhali.easyi18n.model.TranslationData; +import org.jetbrains.annotations.NotNull; + +/** + * Single event listener. + * @author marhali + */ +public interface UpdateDataListener { + /** + * Update the translations based on the supplied data. + * @param data Updated translations + */ + void onUpdateData(@NotNull TranslationData data); +} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/table/TableModelTranslator.java b/src/main/java/de/marhali/easyi18n/model/table/TableModelTranslator.java index 4a23fbc..8f76acb 100644 --- a/src/main/java/de/marhali/easyi18n/model/table/TableModelTranslator.java +++ b/src/main/java/de/marhali/easyi18n/model/table/TableModelTranslator.java @@ -1,10 +1,5 @@ package de.marhali.easyi18n.model.table; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; -import de.marhali.easyi18n.model.LegacyTranslationUpdate; -import de.marhali.easyi18n.model.Translations; - import org.jetbrains.annotations.Nls; import javax.swing.event.TableModelListener; diff --git a/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java b/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java index a479deb..7c7bc4a 100644 --- a/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java +++ b/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java @@ -5,9 +5,6 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.JBColor; import de.marhali.easyi18n.service.SettingsService; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.util.TranslationsUtil; import de.marhali.easyi18n.util.UiUtil; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/de/marhali/easyi18n/service/LegacyDataStore.java b/src/main/java/de/marhali/easyi18n/service/LegacyDataStore.java deleted file mode 100644 index bcf344e..0000000 --- a/src/main/java/de/marhali/easyi18n/service/LegacyDataStore.java +++ /dev/null @@ -1,174 +0,0 @@ -package de.marhali.easyi18n.service; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.project.Project; - -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.io.TranslatorIO; -import de.marhali.easyi18n.model.DataSynchronizer; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; -import de.marhali.easyi18n.model.TranslationDelete; -import de.marhali.easyi18n.model.LegacyTranslationUpdate; -import de.marhali.easyi18n.util.IOUtil; -import de.marhali.easyi18n.util.TranslationsUtil; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.function.Consumer; - -/** - * Factory service to manage localized messages for multiple projects at once. - * @author marhali - */ -@Deprecated -public class LegacyDataStore { - - private static final Map INSTANCES = new WeakHashMap<>(); - - private final Project project; - private final List synchronizer; - - private Translations translations; - private String searchQuery; - - public static LegacyDataStore getInstance(@NotNull Project project) { - LegacyDataStore store = INSTANCES.get(project); - - if(store == null) { - store = new LegacyDataStore(project); - INSTANCES.put(project, store); - } - - return store; - } - - private LegacyDataStore(@NotNull Project project) { - this.project = project; - this.synchronizer = new ArrayList<>(); - this.translations = Translations.empty(); - - // Load data after first initialization - ApplicationManager.getApplication().invokeLater(this::reloadFromDisk, ModalityState.NON_MODAL); - } - - /** - * Registers a new synchronizer which will receive {@link #translations} updates. - * @param synchronizer Synchronizer. See {@link DataSynchronizer} - */ - public void addSynchronizer(DataSynchronizer synchronizer) { - this.synchronizer.add(synchronizer); - } - - /** - * Loads all translations from disk and overrides current {@link #translations} state. - */ - public void reloadFromDisk() { - String localesPath = SettingsService.getInstance(project).getState().getLocalesPath(); - - if(localesPath == null || localesPath.isEmpty()) { - // Propagate empty state - this.translations = Translations.empty(); - synchronize(searchQuery, null); - - } else { - TranslatorIO io = IOUtil.determineFormat(project, localesPath); - - io.read(project, localesPath, (loadedTranslations) -> { - this.translations = loadedTranslations == null ? Translations.empty() : loadedTranslations; - synchronize(searchQuery, null); - }); - } - } - - /** - * Saves the current translation state to disk. See {@link TranslatorIO#save(Project, Translations, String, Consumer)} - * @param callback Complete callback. Indicates if operation was successful(true) or not - */ - public void saveToDisk(@NotNull Consumer callback) { - String localesPath = SettingsService.getInstance(project).getState().getLocalesPath(); - - if(localesPath == null || localesPath.isEmpty()) { // Cannot save without valid path - return; - } - - TranslatorIO io = IOUtil.determineFormat(project, localesPath); - io.save(project, translations, localesPath, callback); - } - - /** - * Propagates provided search string to all synchronizer to display only relevant keys - * @param fullPath Full i18n key (e.g. user.username.title). Can be null to display all keys - */ - public void searchBeyKey(@Nullable String fullPath) { - // Use synchronizer to propagate search instance to all views - synchronize(this.searchQuery = fullPath, null); - } - - /** - * Processes the provided update. Updates translation instance and propagates changes. See {@link DataSynchronizer} - * @param update The update to process. For more information see {@link LegacyTranslationUpdate} - */ - public void processUpdate(LegacyTranslationUpdate update) { - if(update.isDeletion() || update.isKeyChange()) { // Delete origin i18n key - String originKey = update.getOrigin().getKey(); - List sections = TranslationsUtil.getSections(originKey); - String nodeKey = sections.remove(sections.size() - 1); // Remove last node, which needs to be removed by parent - - LocalizedNode node = translations.getNodes(); - for(String section : sections) { - if(node == null) { // Might be possible on multi-delete - break; - } - - node = node.getChildren(section); - } - - if(node != null) { // Only remove if parent exists. Might be already deleted on multi-delete - node.removeChildren(nodeKey); - - // Parent is empty now, we need to remove it as well (except root) - if(node.getChildren().isEmpty() && !node.getKey().equals(LocalizedNode.ROOT_KEY)) { - processUpdate(new TranslationDelete(new LegacyKeyedTranslation( - TranslationsUtil.sectionsToFullPath(sections), null))); - } - } - } - - String scrollTo = update.isDeletion() ? null : update.getChange().getKey(); - - if(!update.isDeletion()) { // Recreate with changed val / create - LocalizedNode node = translations.getOrCreateNode(update.getChange().getKey()); - node.setValue(update.getChange().getTranslations()); - } - - // Persist changes and propagate them on success - saveToDisk(success -> { - if(success) { - synchronize(searchQuery, scrollTo); - } - }); - } - - /** - * @return Current translation state - */ - public @NotNull Translations getTranslations() { - return translations; - } - - /** - * Synchronizes current translation's state to all connected subscribers. - * @param searchQuery Optional search by full key filter (ui view) - * @param scrollTo Optional scroll to full key (ui view) - */ - public void synchronize(@Nullable String searchQuery, @Nullable String scrollTo) { - synchronizer.forEach(subscriber -> subscriber.synchronize(this.translations, searchQuery, scrollTo)); - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java b/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java index 844985a..fb6a6e7 100644 --- a/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java +++ b/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java @@ -7,8 +7,7 @@ import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; -import de.marhali.easyi18n.service.LegacyDataStore; -import de.marhali.easyi18n.service.WindowManager; +import de.marhali.easyi18n.InstanceManager; import de.marhali.easyi18n.action.*; import de.marhali.easyi18n.tabs.TableView; import de.marhali.easyi18n.tabs.TreeView; @@ -48,16 +47,16 @@ public class TranslatorToolWindowFactory implements ToolWindowFactory { actions.add(new AddAction()); actions.add(new ReloadAction()); actions.add(new SettingsAction()); - actions.add(new SearchAction((searchString) -> LegacyDataStore.getInstance(project).searchBeyKey(searchString))); + actions.add(new SearchAction((query) -> InstanceManager.get(project).bus().propagate().onSearchQuery(query))); toolWindow.setTitleActions(actions); // Initialize Window Manager WindowManager.getInstance().initialize(toolWindow, treeView, tableView); // Synchronize ui with underlying data - LegacyDataStore store = LegacyDataStore.getInstance(project); - store.addSynchronizer(treeView); - store.addSynchronizer(tableView); - store.synchronize(null, null); + InstanceManager manager = InstanceManager.get(project); + manager.bus().addListener(treeView); + manager.bus().addListener(tableView); + manager.bus().propagate().onUpdateData(manager.store().getData()); } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/tabs/TableView.java b/src/main/java/de/marhali/easyi18n/tabs/TableView.java index 773038c..c7f2e3b 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/TableView.java +++ b/src/main/java/de/marhali/easyi18n/tabs/TableView.java @@ -4,17 +4,14 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; -import de.marhali.easyi18n.service.LegacyDataStore; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.DataSynchronizer; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; -import de.marhali.easyi18n.model.TranslationDelete; -import de.marhali.easyi18n.model.table.TableModelTranslator; +import de.marhali.easyi18n.InstanceManager; +import de.marhali.easyi18n.model.*; import de.marhali.easyi18n.dialog.EditDialog; import de.marhali.easyi18n.listener.DeleteKeyListener; import de.marhali.easyi18n.listener.PopupClickListener; +import de.marhali.easyi18n.model.bus.BusListener; import de.marhali.easyi18n.renderer.TableRenderer; +import de.marhali.easyi18n.tabs.mapper.TableModelMapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +25,7 @@ import java.util.ResourceBundle; * Shows translation state as table. * @author marhali */ -public class TableView implements DataSynchronizer { +public class TableView implements BusListener { private final Project project; @@ -54,10 +51,10 @@ public class TableView implements DataSynchronizer { if(row >= 0) { String fullPath = String.valueOf(table.getValueAt(row, 0)); - LocalizedNode node = LegacyDataStore.getInstance(project).getTranslations().getNode(fullPath); + Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath); - if(node != null) { - new EditDialog(project, new LegacyKeyedTranslation(fullPath, node.getValue())).showAndHandle(); + if(translation != null) { + new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle(); } } } @@ -67,33 +64,38 @@ public class TableView implements DataSynchronizer { for (int selectedRow : table.getSelectedRows()) { String fullPath = String.valueOf(table.getValueAt(selectedRow, 0)); - LegacyDataStore.getInstance(project).processUpdate( - new TranslationDelete(new LegacyKeyedTranslation(fullPath, null))); + InstanceManager.get(project).processUpdate( + new TranslationDelete(new KeyedTranslation(fullPath, null)) + ); } }; } @Override - public void synchronize(@NotNull Translations translations, - @Nullable String searchQuery, @Nullable String scrollTo) { + public void onUpdateData(@NotNull TranslationData data) { + table.setModel(new TableModelMapper(data, update -> + InstanceManager.get(project).processUpdate(update))); + } - table.setModel(new TableModelTranslator(translations, searchQuery, update -> - LegacyDataStore.getInstance(project).processUpdate(update))); + @Override + public void onFocusKey(@Nullable String key) { + int row = -1; - if(scrollTo != null) { - int row = -1; - - for (int i = 0; i < table.getRowCount(); i++) { - if (String.valueOf(table.getValueAt(i, 0)).equals(scrollTo)) { - row = i; - } - } - - if (row > -1) { // Matched @scrollTo - table.scrollRectToVisible( - new Rectangle(0, (row * table.getRowHeight()) + table.getHeight(), 0, 0)); + for (int i = 0; i < table.getRowCount(); i++) { + if (String.valueOf(table.getValueAt(i, 0)).equals(key)) { + row = i; } } + + if (row > -1) { // Matched @scrollTo + table.scrollRectToVisible( + new Rectangle(0, (row * table.getRowHeight()) + table.getHeight(), 0, 0)); + } + } + + @Override + public void onSearchQuery(@Nullable String query) { + // TODO: handle search functionality } public JPanel getRootPanel() { diff --git a/src/main/java/de/marhali/easyi18n/tabs/TreeView.java b/src/main/java/de/marhali/easyi18n/tabs/TreeView.java index 3bc9ccb..726526b 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/TreeView.java +++ b/src/main/java/de/marhali/easyi18n/tabs/TreeView.java @@ -8,19 +8,20 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.treeStructure.Tree; -import de.marhali.easyi18n.service.LegacyDataStore; -import de.marhali.easyi18n.model.LocalizedNode; -import de.marhali.easyi18n.model.DataSynchronizer; -import de.marhali.easyi18n.model.Translations; -import de.marhali.easyi18n.model.LegacyKeyedTranslation; +import de.marhali.easyi18n.InstanceManager; +import de.marhali.easyi18n.model.KeyedTranslation; +import de.marhali.easyi18n.model.Translation; +import de.marhali.easyi18n.model.TranslationData; import de.marhali.easyi18n.model.TranslationDelete; -import de.marhali.easyi18n.model.tree.TreeModelTranslator; +import de.marhali.easyi18n.model.bus.BusListener; import de.marhali.easyi18n.action.treeview.CollapseTreeViewAction; import de.marhali.easyi18n.action.treeview.ExpandTreeViewAction; import de.marhali.easyi18n.dialog.EditDialog; import de.marhali.easyi18n.listener.DeleteKeyListener; import de.marhali.easyi18n.listener.PopupClickListener; import de.marhali.easyi18n.renderer.TreeRenderer; +import de.marhali.easyi18n.service.SettingsService; +import de.marhali.easyi18n.tabs.mapper.TreeModelMapper; import de.marhali.easyi18n.util.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -36,7 +37,7 @@ import java.util.ResourceBundle; * Show translation state as tree. * @author marhali */ -public class TreeView implements DataSynchronizer { +public class TreeView implements BusListener { private final Project project; @@ -46,6 +47,8 @@ public class TreeView implements DataSynchronizer { private Tree tree; + private TreeModelMapper mapper; + public TreeView(Project project) { this.project = project; @@ -77,19 +80,20 @@ public class TreeView implements DataSynchronizer { } @Override - public void synchronize(@NotNull Translations translations, - @Nullable String searchQuery, @Nullable String scrollTo) { + public void onUpdateData(@NotNull TranslationData data) { + tree.setModel(this.mapper = new TreeModelMapper(data, SettingsService.getInstance(project).getState(), null)); + } - TreeModelTranslator model = new TreeModelTranslator(project, translations, searchQuery); - tree.setModel(model); - - if(searchQuery != null && !searchQuery.isEmpty()) { - expandAll().run(); + @Override + public void onFocusKey(@Nullable String key) { + if(key != null && mapper != null) { + this.tree.scrollPathToVisible(mapper.findTreePath(key)); } + } - if(scrollTo != null) { - tree.scrollPathToVisible(model.findTreePath(scrollTo)); - } + @Override + public void onSearchQuery(@Nullable String query) { + // TODO: handle search functionality } private void handlePopup(MouseEvent e) { @@ -100,10 +104,10 @@ public class TreeView implements DataSynchronizer { if(node.getUserObject() instanceof PresentationData) { String fullPath = TreeUtil.getFullPath(path); - LocalizedNode localizedNode = LegacyDataStore.getInstance(project).getTranslations().getNode(fullPath); + Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath); - if(localizedNode != null) { - new EditDialog(project,new LegacyKeyedTranslation(fullPath, localizedNode.getValue())).showAndHandle(); + if(translation != null) { + new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle(); } } } @@ -120,8 +124,9 @@ public class TreeView implements DataSynchronizer { for (TreePath path : tree.getSelectionPaths()) { String fullPath = TreeUtil.getFullPath(path); - LegacyDataStore.getInstance(project).processUpdate( - new TranslationDelete(new LegacyKeyedTranslation(fullPath, null))); + InstanceManager.get(project).processUpdate( + new TranslationDelete(new KeyedTranslation(fullPath, null)) + ); } }; } diff --git a/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java b/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java new file mode 100644 index 0000000..513b14b --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java @@ -0,0 +1,112 @@ +package de.marhali.easyi18n.tabs.mapper; + +import de.marhali.easyi18n.model.*; + +import de.marhali.easyi18n.model.bus.BusListener; +import de.marhali.easyi18n.model.bus.SearchQueryListener; +import de.marhali.easyi18n.model.bus.UpdateDataListener; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * Mapping {@link TranslationData} to {@link TableModel}. + * @author marhali + */ +public class TableModelMapper implements TableModel { + + private final @NotNull TranslationData data; + private final @NotNull List locales; + private final @NotNull List fullKeys; + + private final @NotNull Consumer updater; + + public TableModelMapper(@NotNull TranslationData data, Consumer updater) { + this.data = data; + this.locales = new ArrayList<>(data.getLocales()); + this.fullKeys = new ArrayList<>(data.getFullKeys()); + + this.updater = updater; + } + + @Override + public int getRowCount() { + return this.fullKeys.size(); + } + + @Override + public int getColumnCount() { + return this.locales.size() + 1; // Number of locales + 1 (key column) + } + + @Nls + @Override + public String getColumnName(int columnIndex) { + if(columnIndex == 0) { + return "Key"; + } + + return "" + this.locales.get(columnIndex - 1) + ""; + } + + @Override + public Class getColumnClass(int columnIndex) { + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return rowIndex > 0; // Everything should be editable except the headline + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if(columnIndex == 0) { // Keys + return this.fullKeys.get(rowIndex); + } + + String key = this.fullKeys.get(rowIndex); + String locale = this.locales.get(columnIndex - 1); + Translation translation = this.data.getTranslation(key); + + return translation == null ? null : translation.get(locale); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + String key = String.valueOf(this.getValueAt(rowIndex, 0)); + Translation translation = this.data.getTranslation(key); + + if(translation == null) { // Unknown cell + return; + } + + String newKey = columnIndex == 0 ? String.valueOf(aValue) : key; + + // Translation content update + if(columnIndex > 0) { + if(aValue == null || ((String) aValue).isEmpty()) { + translation.remove(this.locales.get(columnIndex - 1)); + } else { + translation.put(this.locales.get(columnIndex - 1), String.valueOf(aValue)); + } + } + + TranslationUpdate update = new TranslationUpdate(new KeyedTranslation(key, translation), + new KeyedTranslation(newKey, translation)); + + this.updater.accept(update); + } + + @Override + public void addTableModelListener(TableModelListener l) {} + + @Override + public void removeTableModelListener(TableModelListener l) {} +} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java b/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java new file mode 100644 index 0000000..1c08dac --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java @@ -0,0 +1,104 @@ +package de.marhali.easyi18n.tabs.mapper; + +import com.intellij.ide.projectView.PresentationData; +import com.intellij.ui.JBColor; + +import de.marhali.easyi18n.model.SettingsState; +import de.marhali.easyi18n.model.TranslationData; +import de.marhali.easyi18n.model.TranslationNode; +import de.marhali.easyi18n.util.PathUtil; +import de.marhali.easyi18n.util.UiUtil; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.*; +import java.util.List; +import java.util.Map; + +/** + * Mapping {@link TranslationData} to {@link TreeModel}. + * @author marhali + */ +public class TreeModelMapper extends DefaultTreeModel { + + private final TranslationData data; + private final SettingsState state; + + public TreeModelMapper(TranslationData data, SettingsState state, String searchQuery) { + super(null); + + this.data = data; + this.state = state; + + DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); + this.generateNodes(rootNode, this.data.getRootNode()); + super.setRoot(rootNode); + } + + private void generateNodes(DefaultMutableTreeNode parent, TranslationNode translationNode) { + for(Map.Entry entry : translationNode.getChildren().entrySet()) { + String key = entry.getKey(); + TranslationNode childTranslationNode = entry.getValue(); + + if(!childTranslationNode.isLeaf()) { + // Nested node - run recursively + DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(key); + this.generateNodes(childNode, childTranslationNode); + parent.add(childNode); + } else { + String previewLocale = this.state.getPreviewLocale(); + String sub = "(" + previewLocale + ": " + childTranslationNode.getValue().get(previewLocale) + ")"; + String tooltip = UiUtil.generateHtmlTooltip(childTranslationNode.getValue()); + + PresentationData data = new PresentationData(key, sub, null, null); + data.setTooltip(tooltip); + + if(childTranslationNode.getValue().size() != this.data.getLocales().size()) { + data.setForcedTextForeground(JBColor.RED); + } + + parent.add(new DefaultMutableTreeNode(data)); + } + } + } + + + public @NotNull TreePath findTreePath(@NotNull String fullPath) { + List sections = new PathUtil(this.state.isNestedKeys()).split(fullPath); + Object[] nodes = new Object[sections.size() + 1]; + + int pos = 0; + TreeNode currentNode = (TreeNode) this.getRoot(); + nodes[pos] = currentNode; + + for(String section : sections) { + pos++; + currentNode = this.findNode(currentNode, section); + nodes[pos] = currentNode; + } + + return new TreePath(nodes); + } + + public @Nullable DefaultMutableTreeNode findNode(@NotNull TreeNode parent, @NotNull String key) { + for(int i = 0; i < parent.getChildCount(); i++) { + TreeNode child = parent.getChildAt(i); + + if(child instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode mutableChild = (DefaultMutableTreeNode) child; + String childKey = mutableChild.getUserObject().toString(); + + if(mutableChild.getUserObject() instanceof PresentationData) { + childKey = ((PresentationData) mutableChild.getUserObject()).getPresentableText(); + } + + if(childKey != null && childKey.equals(key)) { + return mutableChild; + } + } + } + + throw new NullPointerException("Cannot find node by key: " + key); + } +} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/util/IOUtil.java b/src/main/java/de/marhali/easyi18n/util/IOUtil.java deleted file mode 100644 index a83629d..0000000 --- a/src/main/java/de/marhali/easyi18n/util/IOUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -package de.marhali.easyi18n.util; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import de.marhali.easyi18n.io.implementation.*; -import de.marhali.easyi18n.io.TranslatorIO; - -import de.marhali.easyi18n.service.SettingsService; -import org.jetbrains.annotations.NotNull; - -import java.io.File; - -/** - * IO operations utility. - * @author marhali - */ -@Deprecated -public class IOUtil { - - /** - * Determines the {@link TranslatorIO} which should be used for the specified directoryPath - * @param project Current intellij project - * @param directoryPath The full path to the parent directory which holds the translation files - * @return IO handler to use for file operations - */ - public static TranslatorIO determineFormat(@NotNull Project project, @NotNull String directoryPath) { - VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(directoryPath)); - - if(directory == null || directory.getChildren() == null) { - throw new IllegalArgumentException("Specified folder is invalid (" + directoryPath + ")"); - } - - VirtualFile[] children = directory.getChildren(); - - for(VirtualFile file : children) { - if(file.isDirectory()) { // Modularized locale files - // ATM we only support modularized JSON files - return new ModularizedJsonTranslatorIO(); - } - - if(!isFileRelevant(project, file)) { - continue; - } - - switch(file.getFileType().getDefaultExtension().toLowerCase()) { - case "json": - return new JsonTranslatorIO(); - case "properties": - return new PropertiesTranslatorIO(); - case "yml": - return new YamlTranslatorIO(); - default: - System.err.println("Unsupported i18n locale file format: " - + file.getFileType().getDefaultExtension()); - } - } - - throw new IllegalStateException("Could not determine i18n format. At least one locale file must be defined"); - } - - /** - * Checks if the provided file matches the file pattern specified by configuration - * @param project Current intellij project - * @param file File to check - * @return True if relevant otherwise false - */ - public static boolean isFileRelevant(@NotNull Project project, @NotNull VirtualFile file) { - String pattern = SettingsService.getInstance(project).getState().getFilePattern(); - return file.getName().matches(pattern); - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/util/JsonUtil.java b/src/main/java/de/marhali/easyi18n/util/JsonUtil.java deleted file mode 100644 index 48c57cf..0000000 --- a/src/main/java/de/marhali/easyi18n/util/JsonUtil.java +++ /dev/null @@ -1,97 +0,0 @@ -package de.marhali.easyi18n.util; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - -import de.marhali.easyi18n.model.LocalizedNode; - -import de.marhali.easyi18n.util.array.JsonArrayUtil; -import org.apache.commons.lang.StringEscapeUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * Json tree utilities for writing and reading {@link LocalizedNode}'s - * @author marhali - */ -public class JsonUtil { - - /** - * Creates a {@link JsonObject} based from an {@link LocalizedNode} - * @param locale Current locale - * @param parent Parent json. Can be an entire json document - * @param node The node instance - */ - public static void writeTree(String locale, JsonObject parent, LocalizedNode node) { - if(node.isLeaf() && !node.getKey().equals(LocalizedNode.ROOT_KEY)) { - if(node.getValue().get(locale) != null) { - - if(JsonArrayUtil.isArray(node.getValue().get(locale))) { - parent.add(node.getKey(), JsonArrayUtil.write(node.getValue().get(locale))); - } else { - String value = StringEscapeUtils.unescapeJava(node.getValue().get(locale)); - parent.add(node.getKey(), new JsonPrimitive(value)); - } - } - - } else { - for(LocalizedNode children : node.getChildren()) { - if(children.isLeaf()) { - writeTree(locale, parent, children); - } else { - JsonObject childrenJson = new JsonObject(); - writeTree(locale, childrenJson, children); - if(childrenJson.size() > 0) { - parent.add(children.getKey(), childrenJson); - } - } - } - } - } - - /** - * Reads a {@link JsonObject} and writes the tree into the provided {@link LocalizedNode} - * @param locale Current locale - * @param json Json to read - * @param data Node. Can be a root node - */ - public static void readTree(String locale, JsonObject json, LocalizedNode data) { - for(Map.Entry entry : json.entrySet()) { - String key = entry.getKey(); - - try { - // Try to go one level deeper - JsonObject childObject = entry.getValue().getAsJsonObject(); - - LocalizedNode childrenNode = data.getChildren(key); - - if(childrenNode == null) { - childrenNode = new LocalizedNode(key, new ArrayList<>()); - data.addChildren(childrenNode); - } - - readTree(locale, childObject, childrenNode); - - } catch(IllegalStateException e) { // Reached end for this node - LocalizedNode leafNode = data.getChildren(key); - - if(leafNode == null) { - leafNode = new LocalizedNode(key, new HashMap<>()); - data.addChildren(leafNode); - } - - Map messages = leafNode.getValue(); - - String value = entry.getValue().isJsonArray() - ? JsonArrayUtil.read(entry.getValue().getAsJsonArray()) - : StringUtil.escapeControls(entry.getValue().getAsString(), true); - - messages.put(locale, value); - leafNode.setValue(messages); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/util/MapUtil.java b/src/main/java/de/marhali/easyi18n/util/MapUtil.java index e7a1c0d..d6b12ad 100644 --- a/src/main/java/de/marhali/easyi18n/util/MapUtil.java +++ b/src/main/java/de/marhali/easyi18n/util/MapUtil.java @@ -1,7 +1,5 @@ package de.marhali.easyi18n.util; -import de.marhali.easyi18n.model.LocalizedNode; - import java.util.List; import java.util.TreeMap; @@ -9,6 +7,7 @@ import java.util.TreeMap; * Map utilities. * @author marhali */ +@Deprecated public class MapUtil { /** diff --git a/src/main/java/de/marhali/easyi18n/util/SortedProperties.java b/src/main/java/de/marhali/easyi18n/util/SortedProperties.java index 5b8f9c7..8a5c321 100644 --- a/src/main/java/de/marhali/easyi18n/util/SortedProperties.java +++ b/src/main/java/de/marhali/easyi18n/util/SortedProperties.java @@ -6,6 +6,7 @@ import java.util.*; * Applies sorting to {@link Properties} files. * @author marhali */ +@Deprecated public class SortedProperties extends Properties { @Override diff --git a/src/main/java/de/marhali/easyi18n/util/TranslationsUtil.java b/src/main/java/de/marhali/easyi18n/util/TranslationsUtil.java deleted file mode 100644 index e26d4e7..0000000 --- a/src/main/java/de/marhali/easyi18n/util/TranslationsUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.marhali.easyi18n.util; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Utility tool to support the translations instance - * @author marhali - */ -@Deprecated // SectionUtil -public class TranslationsUtil { - - /** - * Retrieve all sections for the specified path (mostly fullPath) - * @param path The path - * @return Sections. E.g. input user.username.title -> Output: [user, username, title] - */ - public static @NotNull List getSections(@NotNull String path) { - if(!path.contains(".")) { - return new ArrayList<>(Collections.singletonList(path)); - } - - return new ArrayList<>(Arrays.asList(path.split("\\."))); - } - - /** - * Concatenate the given sections to a single string. - * @param sections The sections - * @return Full path. E.g. input [user, username, title] -> Output: user.username.title - */ - public static @NotNull String sectionsToFullPath(@NotNull List sections) { - StringBuilder builder = new StringBuilder(); - - for (String section : sections) { - if(builder.length() > 0) { - builder.append("."); - } - - builder.append(section); - } - - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/util/TreeUtil.java b/src/main/java/de/marhali/easyi18n/util/TreeUtil.java index 6d9fe91..72a2744 100644 --- a/src/main/java/de/marhali/easyi18n/util/TreeUtil.java +++ b/src/main/java/de/marhali/easyi18n/util/TreeUtil.java @@ -1,7 +1,6 @@ package de.marhali.easyi18n.util; import com.intellij.ide.projectView.PresentationData; -import de.marhali.easyi18n.model.LocalizedNode; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; @@ -20,14 +19,13 @@ public class TreeUtil { public static String getFullPath(TreePath path) { StringBuilder builder = new StringBuilder(); - for (Object obj : path.getPath()) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj; Object value = node.getUserObject(); String section = value instanceof PresentationData ? ((PresentationData) value).getPresentableText() : String.valueOf(value); - if(section == null || section.equals(LocalizedNode.ROOT_KEY)) { // Skip root node + if(section == null) { // Skip empty sections continue; }