From 7762b0cacd0d6b3be0e24eea36c77190b301eb73 Mon Sep 17 00:00:00 2001 From: marhali Date: Thu, 13 Jan 2022 16:00:08 +0100 Subject: [PATCH] add filter functionality for missing translation values Resolves #74 --- CHANGELOG.md | 1 + .../java/de/marhali/easyi18n/DataBus.java | 7 ++++- .../FilterMissingTranslationsAction.java | 30 +++++++++++++++++++ .../easyi18n/model/bus/BusListener.java | 3 +- .../FilterMissingTranslationsListener.java | 13 ++++++++ .../service/TranslatorToolWindowFactory.java | 1 + .../de/marhali/easyi18n/tabs/TableView.java | 8 +++++ .../de/marhali/easyi18n/tabs/TreeView.java | 9 ++++++ .../tabs/mapper/TableModelMapper.java | 21 ++++++++++++- .../easyi18n/tabs/mapper/TreeModelMapper.java | 28 +++++++++++++++-- 10 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/main/java/de/marhali/easyi18n/action/FilterMissingTranslationsAction.java create mode 100644 src/main/java/de/marhali/easyi18n/model/bus/FilterMissingTranslationsListener.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 763d02b..43a76a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - I18n key nesting will now escape every delimiter within a section layer (can be inverted via option) ### Added +- Filter functionality for translations with missing values - Full keyboard shortcut support inside tool-window - Support for dots within key nodes in YAML files diff --git a/src/main/java/de/marhali/easyi18n/DataBus.java b/src/main/java/de/marhali/easyi18n/DataBus.java index 5bd517b..d500232 100644 --- a/src/main/java/de/marhali/easyi18n/DataBus.java +++ b/src/main/java/de/marhali/easyi18n/DataBus.java @@ -43,7 +43,7 @@ public class DataBus { } @Override - public void onFocusKey(@Nullable KeyPath key) { + public void onFocusKey(@NotNull KeyPath key) { listener.forEach(li -> li.onFocusKey(key)); } @@ -51,6 +51,11 @@ public class DataBus { public void onSearchQuery(@Nullable String query) { listener.forEach(li -> li.onSearchQuery(query)); } + + @Override + public void onFilterMissingTranslations(boolean filter) { + listener.forEach(li -> li.onFilterMissingTranslations(filter)); + } }; } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/action/FilterMissingTranslationsAction.java b/src/main/java/de/marhali/easyi18n/action/FilterMissingTranslationsAction.java new file mode 100644 index 0000000..1e13dea --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/action/FilterMissingTranslationsAction.java @@ -0,0 +1,30 @@ +package de.marhali.easyi18n.action; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.Project; +import de.marhali.easyi18n.InstanceManager; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.ResourceBundle; + +/** + * Action which toggles translation filter on missing values. + * @author marhali + */ +public class FilterMissingTranslationsAction extends AnAction { + public FilterMissingTranslationsAction() { + super(ResourceBundle.getBundle("messages").getString("action.toggle-missing"), + null, AllIcons.General.ShowWarning); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + Project project = Objects.requireNonNull(e.getProject()); + boolean enable = e.getPresentation().getIcon() == AllIcons.General.ShowWarning; + e.getPresentation().setIcon(enable ? AllIcons.General.Warning : AllIcons.General.ShowWarning); + InstanceManager.get(project).bus().propagate().onFilterMissingTranslations(enable); + } +} \ 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 index 76a7c17..a48b07c 100644 --- a/src/main/java/de/marhali/easyi18n/model/bus/BusListener.java +++ b/src/main/java/de/marhali/easyi18n/model/bus/BusListener.java @@ -5,4 +5,5 @@ package de.marhali.easyi18n.model.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 +public interface BusListener extends UpdateDataListener, FocusKeyListener, + SearchQueryListener, FilterMissingTranslationsListener {} \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/model/bus/FilterMissingTranslationsListener.java b/src/main/java/de/marhali/easyi18n/model/bus/FilterMissingTranslationsListener.java new file mode 100644 index 0000000..16d3457 --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/model/bus/FilterMissingTranslationsListener.java @@ -0,0 +1,13 @@ +package de.marhali.easyi18n.model.bus; + +/** + * Single event listener. + * @author marhali + */ +public interface FilterMissingTranslationsListener { + /** + * Toggles filter of missing translations + * @param filter True if only translations with missing values should bw shown + */ + void onFilterMissingTranslations(boolean filter); +} \ 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 9a4436f..d0837fa 100644 --- a/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java +++ b/src/main/java/de/marhali/easyi18n/service/TranslatorToolWindowFactory.java @@ -46,6 +46,7 @@ public class TranslatorToolWindowFactory implements ToolWindowFactory, DumbAware // ToolWindow Actions (Can be used for every view) List actions = new ArrayList<>(); actions.add(new AddAction()); + actions.add(new FilterMissingTranslationsAction()); actions.add(new ReloadAction()); actions.add(new SettingsAction()); actions.add(new SearchAction((query) -> InstanceManager.get(project).bus().propagate().onSearchQuery(query))); diff --git a/src/main/java/de/marhali/easyi18n/tabs/TableView.java b/src/main/java/de/marhali/easyi18n/tabs/TableView.java index 596d846..02ad3b7 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/TableView.java +++ b/src/main/java/de/marhali/easyi18n/tabs/TableView.java @@ -107,6 +107,14 @@ public class TableView implements BusListener { } } + @Override + public void onFilterMissingTranslations(boolean filter) { + if(this.currentMapper != null) { + this.currentMapper.onFilterMissingTranslations(filter); + this.table.updateUI(); + } + } + public JPanel getRootPanel() { return rootPanel; } diff --git a/src/main/java/de/marhali/easyi18n/tabs/TreeView.java b/src/main/java/de/marhali/easyi18n/tabs/TreeView.java index 71957ab..dff10ea 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/TreeView.java +++ b/src/main/java/de/marhali/easyi18n/tabs/TreeView.java @@ -106,6 +106,15 @@ public class TreeView implements BusListener { } } + @Override + public void onFilterMissingTranslations(boolean filter) { + if (this.currentMapper != null) { + this.currentMapper.onFilterMissingTranslations(filter); + this.expandAll(); + this.tree.updateUI(); + } + } + private void showEditPopup(@Nullable TreePath path) { if (path == null) { return; diff --git a/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java b/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java index 209f6b0..18137c2 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java +++ b/src/main/java/de/marhali/easyi18n/tabs/mapper/TableModelMapper.java @@ -1,6 +1,7 @@ package de.marhali.easyi18n.tabs.mapper; import de.marhali.easyi18n.model.*; +import de.marhali.easyi18n.model.bus.FilterMissingTranslationsListener; import de.marhali.easyi18n.model.bus.SearchQueryListener; import org.jetbrains.annotations.Nls; @@ -17,7 +18,7 @@ import java.util.function.Consumer; * Mapping {@link TranslationData} to {@link TableModel}. * @author marhali */ -public class TableModelMapper implements TableModel, SearchQueryListener { +public class TableModelMapper implements TableModel, SearchQueryListener, FilterMissingTranslationsListener { private final @NotNull TranslationData data; private final @NotNull KeyPathConverter converter; @@ -63,6 +64,24 @@ public class TableModelMapper implements TableModel, SearchQueryListener { this.fullKeys = matches; } + @Override + public void onFilterMissingTranslations(boolean filter) { + if(!filter) { // Reset + this.fullKeys = new ArrayList<>(this.data.getFullKeys()); + return; + } + + List matches = new ArrayList<>(); + + for(KeyPath key : this.data.getFullKeys()) { + if(this.data.getTranslation(key).values().size() != this.locales.size()) { + matches.add(key); + } + } + + this.fullKeys = matches; + } + @Override public int getRowCount() { return this.fullKeys.size(); diff --git a/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java b/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java index 16753d6..904a667 100644 --- a/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java +++ b/src/main/java/de/marhali/easyi18n/tabs/mapper/TreeModelMapper.java @@ -4,6 +4,7 @@ import com.intellij.ide.projectView.PresentationData; import com.intellij.ui.JBColor; import de.marhali.easyi18n.model.*; +import de.marhali.easyi18n.model.bus.FilterMissingTranslationsListener; import de.marhali.easyi18n.model.bus.SearchQueryListener; import de.marhali.easyi18n.util.UiUtil; @@ -19,7 +20,7 @@ import java.util.Map; * Mapping {@link TranslationData} to {@link TreeModel}. * @author marhali */ -public class TreeModelMapper extends DefaultTreeModel implements SearchQueryListener { +public class TreeModelMapper extends DefaultTreeModel implements SearchQueryListener, FilterMissingTranslationsListener { private final TranslationData data; private final KeyPathConverter converter; @@ -42,7 +43,7 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); TranslationData shadow = new TranslationData(this.state.isSortKeys()); - if(query == null) { + if(query == null) { // Reset this.generateNodes(rootNode, this.data.getRootNode()); super.setRoot(rootNode); return; @@ -71,6 +72,29 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList super.setRoot(rootNode); } + @Override + public void onFilterMissingTranslations(boolean filter) { + DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); + TranslationData shadow = new TranslationData(this.state.isSortKeys()); + + if(!filter) { // Reset + this.generateNodes(rootNode, this.data.getRootNode()); + super.setRoot(rootNode); + return; + } + + for(KeyPath currentKey : this.data.getFullKeys()) { + Translation translation = this.data.getTranslation(currentKey); + + if(translation.values().size() != this.data.getLocales().size()) { + shadow.setTranslation(currentKey, translation); + } + } + + this.generateNodes(rootNode, shadow.getRootNode()); + super.setRoot(rootNode); + } + /** * * @param parent Parent tree node