Scroll to created / edited translation inside Tree-/Table-View
This commit is contained in:
parent
584b9e190f
commit
f3795eacee
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -91,4 +91,42 @@ public class TreeModelTranslator extends DefaultTreeModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TreePath findTreePath(@NotNull String fullPath) {
|
||||
List<String> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user