improve keyboard shortcuts to edit or delete translations

Resolves #71
This commit is contained in:
marhali 2022-01-10 22:18:49 +01:00
parent c6b87f9f90
commit a9748cdea7
5 changed files with 110 additions and 79 deletions

View File

@ -4,16 +4,17 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- Full keyboard shortcut support inside tool-window
- Support for dots within key nodes in YAML files - Support for dots within key nodes in YAML files
### Fixed
- First row inside table view is not editable
- Key focus within tree or table view after translation change
### Changed ### Changed
- Update Qodana to latest version - Update Qodana to latest version
- Allow tool-window rendering in dumb mode - Allow tool-window rendering in dumb mode
### Fixed
- First row inside table view is not editable
- Key focus within tree or table view after translation change
## [1.7.1] ## [1.7.1]
### Fixed ### Fixed
- Vue.js template folding support - Vue.js template folding support

View File

@ -9,16 +9,16 @@ import java.awt.event.KeyListener;
*/ */
public class DeleteKeyListener implements KeyListener { public class DeleteKeyListener implements KeyListener {
private final Runnable deleteRunnable; private final Runnable onActivate;
public DeleteKeyListener(Runnable deleteRunnable) { public DeleteKeyListener(Runnable onActivate) {
this.deleteRunnable = deleteRunnable; this.onActivate = onActivate;
} }
@Override @Override
public void keyTyped(KeyEvent e) { public void keyTyped(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_DELETE) { if(e.getKeyChar() == KeyEvent.VK_DELETE) {
deleteRunnable.run(); this.onActivate.run();
} }
} }

View File

@ -0,0 +1,30 @@
package de.marhali.easyi18n.listener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* Return (\n) keystroke listener.
* @author marhali
*/
public class ReturnKeyListener implements KeyListener {
private final Runnable onActivate;
public ReturnKeyListener(Runnable onActivate) {
this.onActivate = onActivate;
}
@Override
public void keyTyped(KeyEvent e) {
if(e.getKeyChar() == KeyEvent.VK_ENTER) {
this.onActivate.run();
}
}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
}

View File

@ -5,6 +5,7 @@ import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable; import com.intellij.ui.table.JBTable;
import de.marhali.easyi18n.InstanceManager; import de.marhali.easyi18n.InstanceManager;
import de.marhali.easyi18n.listener.ReturnKeyListener;
import de.marhali.easyi18n.model.*; import de.marhali.easyi18n.model.*;
import de.marhali.easyi18n.dialog.EditDialog; import de.marhali.easyi18n.dialog.EditDialog;
import de.marhali.easyi18n.listener.DeleteKeyListener; import de.marhali.easyi18n.listener.DeleteKeyListener;
@ -18,11 +19,11 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
* Shows translation state as table. * Shows translation state as table.
*
* @author marhali * @author marhali
*/ */
public class TableView implements BusListener { public class TableView implements BusListener {
@ -41,36 +42,35 @@ public class TableView implements BusListener {
table = new JBTable(); table = new JBTable();
table.getEmptyText().setText(ResourceBundle.getBundle("messages").getString("view.empty")); table.getEmptyText().setText(ResourceBundle.getBundle("messages").getString("view.empty"));
table.addMouseListener(new PopupClickListener(this::handlePopup)); table.addMouseListener(new PopupClickListener(e -> showEditPopup(table.rowAtPoint(e.getPoint()))));
table.addKeyListener(new DeleteKeyListener(handleDeleteKey())); table.addKeyListener(new ReturnKeyListener(() -> showEditPopup(table.getSelectedRow())));
table.addKeyListener(new DeleteKeyListener(this::deleteSelectedRows));
table.setDefaultRenderer(String.class, new TableRenderer()); table.setDefaultRenderer(String.class, new TableRenderer());
containerPanel.add(new JBScrollPane(table)); containerPanel.add(new JBScrollPane(table));
} }
private void handlePopup(MouseEvent e) { private void showEditPopup(int row) {
int row = table.rowAtPoint(e.getPoint()); if (row < 0) {
return;
}
if(row >= 0) { String fullPath = String.valueOf(table.getValueAt(row, 0));
String fullPath = String.valueOf(table.getValueAt(row, 0)); Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
if(translation != null) { if (translation != null) {
new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle(); new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle();
}
} }
} }
private Runnable handleDeleteKey() { private void deleteSelectedRows() {
return () -> { for (int selectedRow : table.getSelectedRows()) {
for (int selectedRow : table.getSelectedRows()) { String fullPath = String.valueOf(table.getValueAt(selectedRow, 0));
String fullPath = String.valueOf(table.getValueAt(selectedRow, 0));
InstanceManager.get(project).processUpdate( InstanceManager.get(project).processUpdate(
new TranslationDelete(new KeyedTranslation(fullPath, null)) new TranslationDelete(new KeyedTranslation(fullPath, null))
); );
} }
};
} }
@Override @Override
@ -97,7 +97,7 @@ public class TableView implements BusListener {
@Override @Override
public void onSearchQuery(@Nullable String query) { public void onSearchQuery(@Nullable String query) {
if(this.currentMapper != null) { if (this.currentMapper != null) {
this.currentMapper.onSearchQuery(query); this.currentMapper.onSearchQuery(query);
this.table.updateUI(); this.table.updateUI();
} }

View File

@ -9,6 +9,7 @@ import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.treeStructure.Tree; import com.intellij.ui.treeStructure.Tree;
import de.marhali.easyi18n.InstanceManager; import de.marhali.easyi18n.InstanceManager;
import de.marhali.easyi18n.listener.ReturnKeyListener;
import de.marhali.easyi18n.model.KeyedTranslation; import de.marhali.easyi18n.model.KeyedTranslation;
import de.marhali.easyi18n.model.Translation; import de.marhali.easyi18n.model.Translation;
import de.marhali.easyi18n.model.TranslationData; import de.marhali.easyi18n.model.TranslationData;
@ -30,11 +31,11 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*; import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import java.awt.event.MouseEvent;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
* Show translation state as tree. * Show translation state as tree.
*
* @author marhali * @author marhali
*/ */
public class TreeView implements BusListener { public class TreeView implements BusListener {
@ -56,8 +57,9 @@ public class TreeView implements BusListener {
tree.setCellRenderer(new TreeRenderer()); tree.setCellRenderer(new TreeRenderer());
tree.setRootVisible(false); tree.setRootVisible(false);
tree.getEmptyText().setText(ResourceBundle.getBundle("messages").getString("view.empty")); tree.getEmptyText().setText(ResourceBundle.getBundle("messages").getString("view.empty"));
tree.addMouseListener(new PopupClickListener(this::handlePopup)); tree.addMouseListener(new PopupClickListener(e -> showEditPopup(tree.getPathForLocation(e.getX(), e.getY()))));
tree.addKeyListener(new DeleteKeyListener(handleDeleteKey())); tree.addKeyListener(new ReturnKeyListener(() -> showEditPopup(tree.getSelectionPath())));
tree.addKeyListener(new DeleteKeyListener(this::deleteSelectedNodes));
containerPanel.add(new JBScrollPane(tree)); containerPanel.add(new JBScrollPane(tree));
placeActions(); placeActions();
@ -66,8 +68,8 @@ public class TreeView implements BusListener {
private void placeActions() { private void placeActions() {
DefaultActionGroup group = new DefaultActionGroup("TranslationsGroup", false); DefaultActionGroup group = new DefaultActionGroup("TranslationsGroup", false);
ExpandTreeViewAction expand = new ExpandTreeViewAction(expandAll()); ExpandTreeViewAction expand = new ExpandTreeViewAction(this::expandAll);
CollapseTreeViewAction collapse = new CollapseTreeViewAction(collapseAll()); CollapseTreeViewAction collapse = new CollapseTreeViewAction(this::collapseAll);
group.add(collapse); group.add(collapse);
group.add(expand); group.add(expand);
@ -86,13 +88,13 @@ public class TreeView implements BusListener {
@Override @Override
public void onFocusKey(@Nullable String key) { public void onFocusKey(@Nullable String key) {
if(key != null && currentMapper != null) { if (key != null && currentMapper != null) {
TreePath path = currentMapper.findTreePath(key); TreePath path = currentMapper.findTreePath(key);
this.tree.getSelectionModel().setSelectionPath(path); this.tree.getSelectionModel().setSelectionPath(path);
this.tree.scrollPathToVisible(path); this.tree.scrollPathToVisible(path);
if(this.tree.isCollapsed(path)) { if (this.tree.isCollapsed(path)) {
this.tree.expandPath(path); this.tree.expandPath(path);
} }
} }
@ -100,62 +102,60 @@ public class TreeView implements BusListener {
@Override @Override
public void onSearchQuery(@Nullable String query) { public void onSearchQuery(@Nullable String query) {
if(this.currentMapper != null) { if (this.currentMapper != null) {
this.currentMapper.onSearchQuery(query); this.currentMapper.onSearchQuery(query);
this.expandAll().run(); this.expandAll();
this.tree.updateUI(); this.tree.updateUI();
} }
} }
private void handlePopup(MouseEvent e) { private void showEditPopup(@Nullable TreePath path) {
TreePath path = tree.getPathForLocation(e.getX(), e.getY()); if (path == null) {
return;
}
if(path != null) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
if(node.getUserObject() instanceof PresentationData) { if (!(node.getUserObject() instanceof PresentationData)) {
String fullPath = TreeUtil.getFullPath(path); return;
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath); }
if(translation != null) { String fullPath = TreeUtil.getFullPath(path);
new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle(); Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
}
} if (translation == null) {
return;
}
new EditDialog(project, new KeyedTranslation(fullPath, translation)).showAndHandle();
}
private void deleteSelectedNodes() {
TreePath[] paths = tree.getSelectionPaths();
if (paths == null) {
return;
}
for (TreePath path : tree.getSelectionPaths()) {
String fullPath = TreeUtil.getFullPath(path);
InstanceManager.get(project).processUpdate(
new TranslationDelete(new KeyedTranslation(fullPath, null))
);
} }
} }
private Runnable handleDeleteKey() { private void expandAll() {
return () -> { for (int i = 0; i < tree.getRowCount(); i++) {
TreePath[] paths = tree.getSelectionPaths(); tree.expandRow(i);
}
if (paths == null) {
return;
}
for (TreePath path : tree.getSelectionPaths()) {
String fullPath = TreeUtil.getFullPath(path);
InstanceManager.get(project).processUpdate(
new TranslationDelete(new KeyedTranslation(fullPath, null))
);
}
};
} }
private Runnable expandAll() { private void collapseAll() {
return () -> { for (int i = 0; i < tree.getRowCount(); i++) {
for(int i = 0; i < tree.getRowCount(); i++) { tree.collapseRow(i);
tree.expandRow(i); }
}
};
}
private Runnable collapseAll() {
return () -> {
for(int i = 0; i < tree.getRowCount(); i++) {
tree.collapseRow(i);
}
};
} }
public JPanel getRootPanel() { public JPanel getRootPanel() {