From 1efcde7cb2c77c7a33538b82f5b86c0c82193f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 11:25:59 +0200 Subject: [PATCH 01/12] Update dependencies and increase version number --- CHANGELOG.md | 3 +++ gradle.properties | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d60e5e2..65ffacd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ # easy-i18n Changelog ## [Unreleased] +### Changed +- Updated dependencies + ## [1.2.0] ### Added - Sorting for properties files diff --git a/gradle.properties b/gradle.properties index 3ad8dd4..3dd9df5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ pluginGroup = de.marhali.easyi18n pluginName = easy-i18n -pluginVersion = 1.2.0 +pluginVersion = 1.2.1 pluginSinceBuild = 202 pluginUntilBuild = 211.* # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl From 2090167399e9724ef4f6425bb80f32b1cfcba451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 11:34:30 +0200 Subject: [PATCH 02/12] Always synchronize ui with loaded state by reloadFromDisk function --- src/main/java/de/marhali/easyi18n/service/DataStore.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 319b146..e537b43 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -60,6 +60,9 @@ public class DataStore { translations = new Translations(new ArrayList<>(), new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); + // Propagate changes + synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); + } else { TranslatorIO io = IOUtil.determineFormat(localesPath); @@ -74,6 +77,9 @@ public class DataStore { // If state cannot be loaded from disk, show empty instance this.translations = new Translations(new ArrayList<>(), new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); + + // Propagate changes + synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); } }); } From 9a887d9a1f75e588659c3e2c14031dc71889eb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 11:36:38 +0200 Subject: [PATCH 03/12] Add annotation to require not null instance --- src/main/java/de/marhali/easyi18n/service/DataStore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index e537b43..634ebca 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -33,11 +33,11 @@ public class DataStore { private Translations translations; private String searchQuery; - public static DataStore getInstance(Project project) { + public static DataStore getInstance(@NotNull Project project) { return INSTANCE == null ? INSTANCE = new DataStore(project) : INSTANCE; } - private DataStore(Project project) { + private DataStore(@NotNull Project project) { this.project = project; this.synchronizer = new ArrayList<>(); } From 584b9e190f51a3e0a5d7cdfefd0826a2e70bc79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 11:38:50 +0200 Subject: [PATCH 04/12] Synchronize correct translations instance --- src/main/java/de/marhali/easyi18n/service/DataStore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 634ebca..63e3f46 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -71,7 +71,7 @@ public class DataStore { this.translations = translations; // Propagate changes - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); + synchronizer.forEach(synchronizer -> synchronizer.synchronize(this.translations, searchQuery)); } else { // If state cannot be loaded from disk, show empty instance @@ -79,7 +79,7 @@ public class DataStore { new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); // Propagate changes - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); + synchronizer.forEach(synchronizer -> synchronizer.synchronize(this.translations, searchQuery)); } }); } From f3795eacee3f72f3109b6f907008143f377f6f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 16:45:26 +0200 Subject: [PATCH 05/12] Scroll to created / edited translation inside Tree-/Table-View --- CHANGELOG.md | 6 +++ .../easyi18n/model/DataSynchronizer.java | 5 ++- .../model/tree/TreeModelTranslator.java | 38 +++++++++++++++++++ .../marhali/easyi18n/service/DataStore.java | 15 +++++--- .../marhali/easyi18n/ui/tabs/TableView.java | 20 +++++++++- .../de/marhali/easyi18n/ui/tabs/TreeView.java | 12 +++++- 6 files changed, 86 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65ffacd..2146da2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,15 @@ # easy-i18n Changelog ## [Unreleased] +### Added +- Scroll to created / edited translation inside Tree-/Table-View + ### Changed - Updated dependencies +### Fixed +- Always synchronize ui with loaded state by reloadFromDisk function + ## [1.2.0] ### Added - Sorting for properties files diff --git a/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java b/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java index fc25fe4..7cc3e71 100644 --- a/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java +++ b/src/main/java/de/marhali/easyi18n/model/DataSynchronizer.java @@ -12,7 +12,8 @@ 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 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); + 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/tree/TreeModelTranslator.java b/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java index dc87a52..a479deb 100644 --- a/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java +++ b/src/main/java/de/marhali/easyi18n/model/tree/TreeModelTranslator.java @@ -91,4 +91,42 @@ public class TreeModelTranslator extends DefaultTreeModel { } } } + + public TreePath findTreePath(@NotNull String fullPath) { + List sections = TranslationsUtil.getSections(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 = 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); + } } diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 63e3f46..0f8b602 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -61,7 +61,7 @@ public class DataStore { new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); // Propagate changes - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); + synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery, null)); } else { TranslatorIO io = IOUtil.determineFormat(localesPath); @@ -71,7 +71,8 @@ public class DataStore { this.translations = translations; // Propagate changes - synchronizer.forEach(synchronizer -> synchronizer.synchronize(this.translations, searchQuery)); + synchronizer.forEach(synchronizer -> + synchronizer.synchronize(this.translations, searchQuery, null)); } else { // If state cannot be loaded from disk, show empty instance @@ -79,7 +80,8 @@ public class DataStore { new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); // Propagate changes - synchronizer.forEach(synchronizer -> synchronizer.synchronize(this.translations, searchQuery)); + synchronizer.forEach(synchronizer -> + synchronizer.synchronize(this.translations, searchQuery, null)); } }); } @@ -106,7 +108,8 @@ public class DataStore { */ public void searchBeyKey(@Nullable String fullPath) { // Use synchronizer to propagate search instance to all views - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, this.searchQuery = fullPath)); + synchronizer.forEach(synchronizer -> + synchronizer.synchronize(translations, this.searchQuery = fullPath, null)); } /** @@ -139,6 +142,8 @@ public class DataStore { } } + 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()); @@ -147,7 +152,7 @@ public class DataStore { // Persist changes and propagate them on success saveToDisk(success -> { if(success) { - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery)); + synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery, scrollTo)); } }); } diff --git a/src/main/java/de/marhali/easyi18n/ui/tabs/TableView.java b/src/main/java/de/marhali/easyi18n/ui/tabs/TableView.java index ef8b00b..5e81cc1 100644 --- a/src/main/java/de/marhali/easyi18n/ui/tabs/TableView.java +++ b/src/main/java/de/marhali/easyi18n/ui/tabs/TableView.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.awt.event.MouseEvent; import java.util.ResourceBundle; @@ -73,9 +74,26 @@ public class TableView implements DataSynchronizer { } @Override - public void synchronize(@NotNull Translations translations, @Nullable String searchQuery) { + public void synchronize(@NotNull Translations translations, + @Nullable String searchQuery, @Nullable String scrollTo) { + table.setModel(new TableModelTranslator(translations, searchQuery, update -> DataStore.getInstance(project).processUpdate(update))); + + 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)); + } + } } public JPanel getRootPanel() { diff --git a/src/main/java/de/marhali/easyi18n/ui/tabs/TreeView.java b/src/main/java/de/marhali/easyi18n/ui/tabs/TreeView.java index 8014ca5..a4b77cd 100644 --- a/src/main/java/de/marhali/easyi18n/ui/tabs/TreeView.java +++ b/src/main/java/de/marhali/easyi18n/ui/tabs/TreeView.java @@ -20,6 +20,7 @@ import de.marhali.easyi18n.ui.dialog.EditDialog; import de.marhali.easyi18n.ui.listener.DeleteKeyListener; import de.marhali.easyi18n.ui.listener.PopupClickListener; import de.marhali.easyi18n.ui.renderer.TreeRenderer; +import de.marhali.easyi18n.util.TranslationsUtil; import de.marhali.easyi18n.util.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -75,12 +76,19 @@ public class TreeView implements DataSynchronizer { } @Override - public void synchronize(@NotNull Translations translations, @Nullable String searchQuery) { - tree.setModel(new TreeModelTranslator(project, translations, searchQuery)); + public void synchronize(@NotNull Translations translations, + @Nullable String searchQuery, @Nullable String scrollTo) { + + TreeModelTranslator model = new TreeModelTranslator(project, translations, searchQuery); + tree.setModel(model); if(searchQuery != null && !searchQuery.isEmpty()) { expandAll().run(); } + + if(scrollTo != null) { + tree.scrollPathToVisible(model.findTreePath(scrollTo)); + } } private void handlePopup(MouseEvent e) { From 5e922512fb237244e05970117daa5d7dee76f5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 16:54:32 +0200 Subject: [PATCH 06/12] Always load translations after singleton initialization to ensure that data is loaded --- src/main/java/de/marhali/easyi18n/service/DataStore.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 0f8b602..3fd77b8 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -40,6 +40,8 @@ public class DataStore { private DataStore(@NotNull Project project) { this.project = project; this.synchronizer = new ArrayList<>(); + + reloadFromDisk(); } /** @@ -160,7 +162,7 @@ public class DataStore { /** * @return Current translation state */ - public Translations getTranslations() { + public @NotNull Translations getTranslations() { return translations; } } \ No newline at end of file From 52d5aed0006694dbe80dd04e80629365c18a75cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Tue, 25 May 2021 17:08:29 +0200 Subject: [PATCH 07/12] Fix npe if translation is unknown --- .../marhali/easyi18n/ui/editor/I18nCompletionProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/marhali/easyi18n/ui/editor/I18nCompletionProvider.java b/src/main/java/de/marhali/easyi18n/ui/editor/I18nCompletionProvider.java index 75e44a0..bc77b00 100644 --- a/src/main/java/de/marhali/easyi18n/ui/editor/I18nCompletionProvider.java +++ b/src/main/java/de/marhali/easyi18n/ui/editor/I18nCompletionProvider.java @@ -24,7 +24,7 @@ public class I18nCompletionProvider extends CompletionProvider Date: Tue, 25 May 2021 17:10:08 +0200 Subject: [PATCH 08/12] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2146da2..4604a63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Updated dependencies ### Fixed +- NullPointerException's on translation annotation / completion inside editor - Always synchronize ui with loaded state by reloadFromDisk function ## [1.2.0] From a3f6545feaf2f9f480077afaf773783e6843844c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Wed, 26 May 2021 11:28:28 +0200 Subject: [PATCH 09/12] Load translations via data store to ensure that data will be loaded without an opened ui --- CHANGELOG.md | 1 + .../easyi18n/TranslatorToolWindowFactory.java | 4 +--- .../de/marhali/easyi18n/model/Translations.java | 6 +++++- .../de/marhali/easyi18n/service/DataStore.java | 17 ++++++++++------- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4604a63..c0d239a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed - Updated dependencies +- Load translations even if ui tool window is not opened ### Fixed - NullPointerException's on translation annotation / completion inside editor diff --git a/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java b/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java index 38efd01..9a2ed43 100644 --- a/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java +++ b/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java @@ -54,11 +54,9 @@ public class TranslatorToolWindowFactory implements ToolWindowFactory { // Initialize Window Manager WindowManager.getInstance().initialize(toolWindow, treeView, tableView); - // Initialize data store and load from disk + // Synchronize ui with underlying data DataStore store = DataStore.getInstance(project); store.addSynchronizer(treeView); store.addSynchronizer(tableView); - - store.reloadFromDisk(); } } \ 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 index 0d84dd5..44bd03f 100644 --- a/src/main/java/de/marhali/easyi18n/model/Translations.java +++ b/src/main/java/de/marhali/easyi18n/model/Translations.java @@ -14,6 +14,10 @@ import java.util.List; */ public class Translations { + public static Translations empty() { + return new Translations(new ArrayList<>(), new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); + } + @NotNull private final List locales; @@ -34,7 +38,7 @@ public class Translations { return locales; } - public LocalizedNode getNodes() { + public @NotNull LocalizedNode getNodes() { return nodes; } diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 3fd77b8..93331ce 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -1,5 +1,7 @@ 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; @@ -40,8 +42,10 @@ public class DataStore { private DataStore(@NotNull Project project) { this.project = project; this.synchronizer = new ArrayList<>(); + this.translations = Translations.empty(); - reloadFromDisk(); + // Load data after first initialization + ApplicationManager.getApplication().invokeLater(this::reloadFromDisk, ModalityState.NON_MODAL); } /** @@ -59,10 +63,8 @@ public class DataStore { String localesPath = SettingsService.getInstance(project).getState().getLocalesPath(); if(localesPath == null || localesPath.isEmpty()) { - translations = new Translations(new ArrayList<>(), - new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); - - // Propagate changes + // Propagate empty state + translations = Translations.empty(); synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery, null)); } else { @@ -78,8 +80,7 @@ public class DataStore { } else { // If state cannot be loaded from disk, show empty instance - this.translations = new Translations(new ArrayList<>(), - new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>())); + this.translations = Translations.empty(); // Propagate changes synchronizer.forEach(synchronizer -> @@ -87,6 +88,8 @@ public class DataStore { } }); } + + System.out.println("reloadFromDisk()"); } /** From a8b6938ac9d8e38c24c41ee56a7663b4903acf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Wed, 26 May 2021 16:41:55 +0200 Subject: [PATCH 10/12] Synchronize tool window after first initialization --- .../java/de/marhali/easyi18n/TranslatorToolWindowFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java b/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java index 9a2ed43..281419f 100644 --- a/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java +++ b/src/main/java/de/marhali/easyi18n/TranslatorToolWindowFactory.java @@ -58,5 +58,6 @@ public class TranslatorToolWindowFactory implements ToolWindowFactory { DataStore store = DataStore.getInstance(project); store.addSynchronizer(treeView); store.addSynchronizer(tableView); + store.synchronize(null, null); } } \ No newline at end of file From d872f3e89adb4a6a67ba395e09989d65cb7b4c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Wed, 26 May 2021 16:43:54 +0200 Subject: [PATCH 11/12] Support multiple opened projects --- CHANGELOG.md | 1 + .../marhali/easyi18n/service/DataStore.java | 54 ++++++++++--------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d239a..85609c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## [Unreleased] ### Added - Scroll to created / edited translation inside Tree-/Table-View +- Support for working with multiple projects at once ### Changed - Updated dependencies diff --git a/src/main/java/de/marhali/easyi18n/service/DataStore.java b/src/main/java/de/marhali/easyi18n/service/DataStore.java index 93331ce..4047bba 100644 --- a/src/main/java/de/marhali/easyi18n/service/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/service/DataStore.java @@ -19,15 +19,17 @@ 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; /** - * Singleton service to manage localized messages. + * Factory service to manage localized messages for multiple projects at once. * @author marhali */ public class DataStore { - private static DataStore INSTANCE; + private static final Map INSTANCES = new WeakHashMap<>(); private final Project project; private final List synchronizer; @@ -36,7 +38,14 @@ public class DataStore { private String searchQuery; public static DataStore getInstance(@NotNull Project project) { - return INSTANCE == null ? INSTANCE = new DataStore(project) : INSTANCE; + DataStore store = INSTANCES.get(project); + + if(store == null) { + store = new DataStore(project); + INSTANCES.put(project, store); + } + + return store; } private DataStore(@NotNull Project project) { @@ -64,32 +73,17 @@ public class DataStore { if(localesPath == null || localesPath.isEmpty()) { // Propagate empty state - translations = Translations.empty(); - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery, null)); + this.translations = Translations.empty(); + synchronize(searchQuery, null); } else { TranslatorIO io = IOUtil.determineFormat(localesPath); - io.read(project, localesPath, (translations) -> { - if(translations != null) { // Read was successful - this.translations = translations; - - // Propagate changes - synchronizer.forEach(synchronizer -> - synchronizer.synchronize(this.translations, searchQuery, null)); - - } else { - // If state cannot be loaded from disk, show empty instance - this.translations = Translations.empty(); - - // Propagate changes - synchronizer.forEach(synchronizer -> - synchronizer.synchronize(this.translations, searchQuery, null)); - } + io.read(project, localesPath, (loadedTranslations) -> { + this.translations = loadedTranslations == null ? Translations.empty() : loadedTranslations; + synchronize(searchQuery, null); }); } - - System.out.println("reloadFromDisk()"); } /** @@ -113,8 +107,7 @@ public class DataStore { */ public void searchBeyKey(@Nullable String fullPath) { // Use synchronizer to propagate search instance to all views - synchronizer.forEach(synchronizer -> - synchronizer.synchronize(translations, this.searchQuery = fullPath, null)); + synchronize(this.searchQuery = fullPath, null); } /** @@ -157,7 +150,7 @@ public class DataStore { // Persist changes and propagate them on success saveToDisk(success -> { if(success) { - synchronizer.forEach(synchronizer -> synchronizer.synchronize(translations, searchQuery, scrollTo)); + synchronize(searchQuery, scrollTo); } }); } @@ -168,4 +161,13 @@ public class DataStore { 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 From ebfef00318b75df4f4ddf9ebf21132e0f0a6b9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Ha=C3=9Flinger?= Date: Wed, 26 May 2021 16:46:10 +0200 Subject: [PATCH 12/12] Update version to 1.3.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3dd9df5..795629b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ pluginGroup = de.marhali.easyi18n pluginName = easy-i18n -pluginVersion = 1.2.1 +pluginVersion = 1.3.0 pluginSinceBuild = 202 pluginUntilBuild = 211.* # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl