ResourceBundleEditor: added context menu for translation editors + action to propagate value across all of translations

This commit is contained in:
Dmitry Batkovich
2015-05-27 14:57:25 +03:00
parent 2ada5c67ad
commit 50eefc6121
5 changed files with 96 additions and 61 deletions
@@ -38,7 +38,6 @@ import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.PropertiesResourceBundleUtil;
import com.intellij.lang.properties.psi.impl.PropertyKeyImpl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
@@ -50,7 +49,6 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.EditorMouseAdapter;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -85,7 +83,6 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
@@ -100,7 +97,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private final StructureViewComponent myStructureViewComponent;
private final Map<PropertiesFile, Editor> myEditors;
private final ResourceBundle myResourceBundle;
private final ResourceBundlePropertiesInsertManager myPropertiesInsertDeleteManager;
private final ResourceBundlePropertiesUpdateManager myPropertiesInsertDeleteManager;
private final Map<PropertiesFile, JPanel> myTitledPanels;
private final JComponent myNoPropertySelectedPanel = new NoPropertySelectedPanel().getComponent();
private final Project myProject;
@@ -134,7 +131,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
splitPanel.add(splitter, BorderLayout.CENTER);
myResourceBundle = resourceBundle;
myPropertiesInsertDeleteManager = ResourceBundlePropertiesInsertManagerImpl.create(resourceBundle);
myPropertiesInsertDeleteManager = ResourceBundlePropertiesUpdateManagerImpl.create(resourceBundle);
myPropertiesAnchorizer = new PropertiesAnchorizer(myResourceBundle.getProject());
myStructureViewComponent = new ResourceBundleStructureViewComponent(myResourceBundle, this, myPropertiesAnchorizer);
@@ -155,7 +152,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
if (e.getOldLeadSelectionPath() != null) {
for (Map.Entry<PropertiesFile, Editor> entry : myEditors.entrySet()) {
if (entry.getValue() == mySelectedEditor) {
writeEditorPropertyValue(mySelectedEditor, entry.getKey(), selectedProperty.getName());
writeEditorPropertyValue(selectedProperty.getName(), mySelectedEditor, entry.getKey());
break;
}
}
@@ -211,7 +208,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
}
@NotNull
public ResourceBundlePropertiesInsertManager getPropertiesInsertDeleteManager() {
public ResourceBundlePropertiesUpdateManager getPropertiesInsertDeleteManager() {
return myPropertiesInsertDeleteManager;
}
@@ -341,7 +338,9 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return value instanceof ResourceBundleEditorViewElement ? (ResourceBundleEditorViewElement) value : null;
}
private void writeEditorPropertyValue(final Editor editor, final PropertiesFile propertiesFile, final @Nullable String propertyName) {
private void writeEditorPropertyValue(final @Nullable String propertyName,
final @NotNull Editor editor,
final @NotNull PropertiesFile propertiesFile) {
final String currentValue = editor.getDocument().getText();
final String currentSelectedProperty = propertyName == null ? getSelectedPropertyName() : propertyName;
if (currentSelectedProperty == null) {
@@ -354,14 +353,8 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
@Override
public void run() {
final IProperty property = propertiesFile.findPropertyByKey(currentSelectedProperty);
try {
if (property == null) {
myPropertiesInsertDeleteManager.insertTranslation(currentSelectedProperty, currentValue, propertiesFile);
}
else {
property.setValue(currentValue);
}
myPropertiesInsertDeleteManager.insertOrUpdateTranslation(currentSelectedProperty, currentValue, propertiesFile);
}
catch (final IncorrectOperationException e) {
LOG.error(e);
@@ -418,7 +411,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
@Override
public void focusLost(final Editor eventEditor) {
writeEditorPropertyValue(editor, propertiesFile, null);
writeEditorPropertyValue(null, editor, propertiesFile);
}
});
gc.gridx = 0;
@@ -847,7 +840,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
if (mySelectedEditor != null) {
for (final Map.Entry<PropertiesFile, Editor> entry : myEditors.entrySet()) {
if (mySelectedEditor.equals(entry.getValue())) {
writeEditorPropertyValue(mySelectedEditor, entry.getKey(), null);
writeEditorPropertyValue(null, mySelectedEditor, entry.getKey());
}
}
}
@@ -893,7 +886,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return editor;
}
private static void reinitSettings(final EditorEx editor) {
private void reinitSettings(final EditorEx editor) {
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
editor.setColorsScheme(scheme);
EditorSettings settings = editor.getSettings();
@@ -914,7 +907,42 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
@Override
public void invokePopup(EditorMouseEvent event) {
if (!event.isConsumed() && event.getArea() == EditorMouseEventArea.EDITING_AREA) {
ActionGroup group = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_CUT_COPY_PASTE);
DefaultActionGroup group = new DefaultActionGroup();
group.copyFromGroup((DefaultActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_CUT_COPY_PASTE));
group.addSeparator();
group.add(new AnAction("Propagate Value Across of Resource Bundle") {
@Override
public void actionPerformed(AnActionEvent e) {
final String valueToPropagate = editor.getDocument().getText();
final String currentSelectedProperty = getSelectedPropertyName();
if (currentSelectedProperty == null) {
return;
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
@Override
public void run() {
try {
for (Map.Entry<PropertiesFile, Editor> entry : myEditors.entrySet()) {
final Editor translationEditor = entry.getValue();
if (translationEditor != editor) {
final PropertiesFile propertiesFile = entry.getKey();
myPropertiesInsertDeleteManager.insertOrUpdateTranslation(currentSelectedProperty, valueToPropagate, propertiesFile);
translationEditor.getDocument().setText(valueToPropagate);
}
}
}
catch (final IncorrectOperationException e) {
LOG.error(e);
}
}
});
}
});
}
});
EditorPopupHandler handler = EditorActionUtil.createEditorPopupHandler(group);
handler.invokePopup(event);
event.consume();
@@ -16,26 +16,27 @@
package com.intellij.lang.properties.editor;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.util.IncorrectOperationException;
/**
* @author Dmitry Batkovich
*/
public interface ResourceBundlePropertiesInsertManager {
public interface ResourceBundlePropertiesUpdateManager {
void insertNewProperty(String key, String value);
void insertTranslation(String key, String value, PropertiesFile propertiesFile);
void insertOrUpdateTranslation(String key, String value, PropertiesFile propertiesFile) throws IncorrectOperationException;
void reload();
class Stub implements ResourceBundlePropertiesInsertManager {
public static final ResourceBundlePropertiesInsertManager INSTANCE = new Stub();
class Stub implements ResourceBundlePropertiesUpdateManager {
public static final ResourceBundlePropertiesUpdateManager INSTANCE = new Stub();
@Override
public void insertNewProperty(String key, String value) {
}
@Override
public void insertTranslation(String key, String value, PropertiesFile propertiesFile) {
public void insertOrUpdateTranslation(String key, String value, PropertiesFile propertiesFile) {
}
@Override
@@ -26,6 +26,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.GraphGenerator;
@@ -37,26 +38,26 @@ import java.util.*;
/**
* @author Dmitry Batkovich
*/
public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundlePropertiesInsertManager {
private final static Logger LOG = Logger.getInstance(ResourceBundlePropertiesInsertManagerImpl.class);
public class ResourceBundlePropertiesUpdateManagerImpl implements ResourceBundlePropertiesUpdateManager {
private final static Logger LOG = Logger.getInstance(ResourceBundlePropertiesUpdateManagerImpl.class);
private final ResourceBundle myResourceBundle;
private boolean myOrdered;
private boolean myAlphaSorted;
private List<String> myKeysOrder;
private ResourceBundlePropertiesInsertManagerImpl(ResourceBundle bundle) {
private ResourceBundlePropertiesUpdateManagerImpl(ResourceBundle bundle) {
myResourceBundle = bundle;
reload();
}
public static ResourceBundlePropertiesInsertManager create(ResourceBundle bundle) {
public static ResourceBundlePropertiesUpdateManager create(ResourceBundle bundle) {
for (PropertiesFile file : bundle.getPropertiesFiles()) {
if (!(file instanceof PropertiesFileImpl)) {
return ResourceBundlePropertiesInsertManager.Stub.INSTANCE;
return ResourceBundlePropertiesUpdateManager.Stub.INSTANCE;
}
}
return new ResourceBundlePropertiesInsertManagerImpl(bundle);
return new ResourceBundlePropertiesUpdateManagerImpl(bundle);
}
@Override
@@ -76,15 +77,21 @@ public class ResourceBundlePropertiesInsertManagerImpl implements ResourceBundle
}
@Override
public void insertTranslation(String key, String value, final PropertiesFile propertiesFile) {
public void insertOrUpdateTranslation(String key, String value, final PropertiesFile propertiesFile) throws IncorrectOperationException {
final IProperty property = propertiesFile.findPropertyByKey(key);
if (property != null) {
property.setValue(value);
}
if (myOrdered) {
if (myAlphaSorted) {
propertiesFile.addProperty(key, value);
return;
}
final Pair<IProperty, Integer> propertyAndPosition = findExistedPrevSiblingProperty(key, propertiesFile);
propertiesFile.addPropertyAfter(key, value, propertyAndPosition == null ? null :(Property)propertyAndPosition.getFirst());
} else {
propertiesFile.addPropertyAfter(key, value, propertyAndPosition == null ? null : (Property)propertyAndPosition.getFirst());
}
else {
insertPropertyLast(key, value, propertiesFile);
}
}
@@ -26,11 +26,9 @@ import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.impl.FakePsiElement;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import com.intellij.ui.PopupHandler;
@@ -149,10 +147,10 @@ public class ResourceBundleStructureViewComponent extends PropertiesGroupingStru
}
private class PsiElementsDeleteProvider implements DeleteProvider {
private final ResourceBundlePropertiesInsertManager myInsertDeleteManager;
private final ResourceBundlePropertiesUpdateManager myInsertDeleteManager;
private final PsiElement[] myElements;
private PsiElementsDeleteProvider(ResourceBundlePropertiesInsertManager insertDeleteManager, final PsiElement[] elements) {
private PsiElementsDeleteProvider(ResourceBundlePropertiesUpdateManager insertDeleteManager, final PsiElement[] elements) {
myInsertDeleteManager = insertDeleteManager;
myElements = elements;
}
@@ -15,8 +15,8 @@
*/
package com.intellij.lang.properties;
import com.intellij.lang.properties.editor.ResourceBundlePropertiesInsertManager;
import com.intellij.lang.properties.editor.ResourceBundlePropertiesInsertManagerImpl;
import com.intellij.lang.properties.editor.ResourceBundlePropertiesUpdateManager;
import com.intellij.lang.properties.editor.ResourceBundlePropertiesUpdateManagerImpl;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.psi.PsiFile;
@@ -39,26 +39,27 @@ public class ResourceBundleEditorInsertManagerTest extends LightPlatformCodeInsi
myFixture.configureByFile(getTestName(true) + "/p_fr.properties");
final PsiFile file = myFixture.configureByFile(getTestName(true) + "/p_ru.properties");
final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
final ResourceBundlePropertiesInsertManager manager = ResourceBundlePropertiesInsertManagerImpl.create(propertiesFile.getResourceBundle());
final ResourceBundlePropertiesUpdateManager
manager = ResourceBundlePropertiesUpdateManagerImpl.create(propertiesFile.getResourceBundle());
manager.reload();
assertTrue(((ResourceBundlePropertiesInsertManagerImpl)manager).isAlphaSorted());
assertTrue(((ResourceBundlePropertiesUpdateManagerImpl)manager).isAlphaSorted());
}
public void testAddToAlphaOrdered() {
doTest(new TestAction() {
@Override
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesInsertManagerImpl manager) {
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesUpdateManagerImpl manager) {
assertTrue(manager.isAlphaSorted());
manager.insertNewProperty("l", "v");
manager.insertTranslation("d", "v", baseFile);
manager.insertTranslation("r", "v", translationFile);
manager.insertOrUpdateTranslation("d", "v", baseFile);
manager.insertOrUpdateTranslation("r", "v", translationFile);
manager.insertNewProperty("a", "v");
manager.insertTranslation("a", "v", translationFile);
manager.insertOrUpdateTranslation("a", "v", translationFile);
manager.insertNewProperty("z", "v");
manager.insertTranslation("z", "v", translationFile);
manager.insertTranslation("l", "v", translationFile);
manager.insertTranslation("e", "v", translationFile);
manager.insertTranslation("t", "v", baseFile);
manager.insertOrUpdateTranslation("z", "v", translationFile);
manager.insertOrUpdateTranslation("l", "v", translationFile);
manager.insertOrUpdateTranslation("e", "v", translationFile);
manager.insertOrUpdateTranslation("t", "v", baseFile);
}
});
}
@@ -66,13 +67,13 @@ public class ResourceBundleEditorInsertManagerTest extends LightPlatformCodeInsi
public void testAddToOrdered() {
doTest(new TestAction() {
@Override
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesInsertManagerImpl manager) {
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesUpdateManagerImpl manager) {
assertFalse(manager.isAlphaSorted());
manager.insertNewProperty("bnm", "v");
manager.insertNewProperty("uio", "v");
manager.insertTranslation("uio", "v", translationFile);
manager.insertTranslation("qwe", "v", translationFile);
manager.insertTranslation("zxc", "v", baseFile);
manager.insertOrUpdateTranslation("uio", "v", translationFile);
manager.insertOrUpdateTranslation("qwe", "v", translationFile);
manager.insertOrUpdateTranslation("zxc", "v", baseFile);
}
});
}
@@ -80,13 +81,13 @@ public class ResourceBundleEditorInsertManagerTest extends LightPlatformCodeInsi
public void testAddToUnordered() {
doTest(new TestAction() {
@Override
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesInsertManagerImpl manager) {
public void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesUpdateManagerImpl manager) {
assertFalse(manager.isAlphaSorted());
manager.insertTranslation("bnm", "v", translationFile);
manager.insertOrUpdateTranslation("bnm", "v", translationFile);
manager.insertNewProperty("ghj", "v");
manager.insertTranslation("ghj", "v", translationFile);
manager.insertOrUpdateTranslation("ghj", "v", translationFile);
manager.insertNewProperty("uio", "v");
manager.insertTranslation("uio", "v", translationFile);
manager.insertOrUpdateTranslation("uio", "v", translationFile);
}
});
}
@@ -97,15 +98,15 @@ public class ResourceBundleEditorInsertManagerTest extends LightPlatformCodeInsi
final PropertiesFile basePropertiesFile = PropertiesImplUtil.getPropertiesFile(baseFile);
assertNotNull(basePropertiesFile);
final ResourceBundle bundle = basePropertiesFile.getResourceBundle();
final ResourceBundlePropertiesInsertManager manager = ResourceBundlePropertiesInsertManagerImpl.create(bundle);
assertInstanceOf(manager, ResourceBundlePropertiesInsertManagerImpl.class);
final ResourceBundlePropertiesUpdateManager manager = ResourceBundlePropertiesUpdateManagerImpl.create(bundle);
assertInstanceOf(manager, ResourceBundlePropertiesUpdateManagerImpl.class);
testAction.doTestAction(basePropertiesFile, PropertiesImplUtil.getPropertiesFile(translationFile),
(ResourceBundlePropertiesInsertManagerImpl)manager);
(ResourceBundlePropertiesUpdateManagerImpl)manager);
myFixture.checkResultByFile(getTestName(true) + "/p.properties", getTestName(true) + "/p-after.properties", true);
myFixture.checkResultByFile(getTestName(true) + "/p_en.properties", getTestName(true) + "/p-after_en.properties",true);
}
private interface TestAction {
void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesInsertManagerImpl manager);
void doTestAction(PropertiesFile baseFile, PropertiesFile translationFile, ResourceBundlePropertiesUpdateManagerImpl manager);
}
}