diff --git a/src/main/java/de/marhali/easyi18n/action/AddAction.java b/src/main/java/de/marhali/easyi18n/action/AddAction.java index b356b9a..05be4f1 100644 --- a/src/main/java/de/marhali/easyi18n/action/AddAction.java +++ b/src/main/java/de/marhali/easyi18n/action/AddAction.java @@ -6,10 +6,10 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.project.Project; import com.intellij.ui.content.Content; -import de.marhali.easyi18n.model.KeyPath; -import de.marhali.easyi18n.model.KeyPathConverter; -import de.marhali.easyi18n.service.WindowManager; import de.marhali.easyi18n.dialog.AddDialog; +import de.marhali.easyi18n.model.translation.KeyPath; +import de.marhali.easyi18n.service.WindowManager; +import de.marhali.easyi18n.util.KeyPathConverter; import de.marhali.easyi18n.util.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -32,7 +32,7 @@ public class AddAction extends AnAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { - new AddDialog(Objects.requireNonNull(e.getProject()), detectPreKey(e.getProject())).showAndHandle(); + new AddDialog(Objects.requireNonNull(e.getProject()), detectPreKey(e.getProject()), null).showAndHandle(); } private @Nullable KeyPath detectPreKey(@NotNull Project project) { @@ -58,7 +58,7 @@ public class AddAction extends AnAction { if(row >= 0) { String path = String.valueOf(window.getTableView().getTable().getValueAt(row, 0)); - return converter.split(path); + return converter.fromString(path); } } diff --git a/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java b/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java index dd886b0..0998611 100644 --- a/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java +++ b/src/main/java/de/marhali/easyi18n/dialog/AddDialog.java @@ -3,112 +3,64 @@ package de.marhali.easyi18n.dialog; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.ui.components.JBLabel; -import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.components.JBTextField; import de.marhali.easyi18n.InstanceManager; -import de.marhali.easyi18n.model.*; +import de.marhali.easyi18n.model.TranslationCreate; +import de.marhali.easyi18n.model.translation.KeyPath; +import de.marhali.easyi18n.model.translation.Translation; +import de.marhali.easyi18n.model.translation.TranslationValue; +import de.marhali.easyi18n.settings.ProjectSettingsService; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.EtchedBorder; -import java.awt.*; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; /** - * Create translation dialog. + * Dialog to create a new translation with all associated locale values. + * Supports optional prefill technique for translation key or locale value. * @author marhali */ -public class AddDialog { +public class AddDialog extends TranslationDialog { - private final @NotNull Project project; - private final @NotNull KeyPathConverter converter; - - private @NotNull KeyPath preKey; - - private JBTextField keyTextField; - private Map valueTextFields; - - public AddDialog(@NotNull Project project, @Nullable KeyPath preKey) { - this(project); - this.preKey = preKey == null ? new KeyPath() : preKey; + /** + * Constructs a new create dialog with prefilled fields + * @param project Opened project + * @param prefillKey Prefill translation key + * @param prefillLocale Prefill preview locale value + */ + public AddDialog(@NotNull Project project, @Nullable KeyPath prefillKey, @Nullable String prefillLocale) { + super(project, new Translation(prefillKey != null ? prefillKey : new KeyPath(), + prefillLocale != null + ? new TranslationValue(ProjectSettingsService.get(project).getState().getPreviewLocale(), prefillLocale) + : null) + ); } + /** + * Constructs a new create dialog without prefilled fields. + * @param project Opened project + */ public AddDialog(@NotNull Project project) { - this.project = project; - this.converter = new KeyPathConverter(project); - this.preKey = new KeyPath(); + this(project, new KeyPath(), ""); } - public void showAndHandle() { - int code = prepare().show(); - - if(code == DialogWrapper.OK_EXIT_CODE) { - saveTranslation(); - } - } - - private void saveTranslation() { - Translation translation = new Translation(); - - valueTextFields.forEach((k, v) -> { - if(!v.getText().isEmpty()) { - translation.put(k, v.getText()); - } - }); - - KeyedTranslation keyedTranslation = new KeyedTranslation(converter.split(keyTextField.getText()), translation); - TranslationCreate creation = new TranslationCreate(keyedTranslation); - InstanceManager.get(project).processUpdate(creation); - } - - private DialogBuilder prepare() { - JPanel rootPanel = new JPanel(); - rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS)); - - JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2, 2)); - JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key")); - keyTextField = new JBTextField(this.converter.concat(this.preKey)); - keyLabel.setLabelFor(keyTextField); - keyPanel.add(keyLabel); - keyPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - keyPanel.add(keyTextField); - rootPanel.add(keyPanel); - - if(!this.preKey.isEmpty()) { // Add delimiter if pre key is defined - keyTextField.setText(keyTextField.getText() + KeyPath.DELIMITER); - } - - JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2)); - valueTextFields = new HashMap<>(); - - for(String locale : InstanceManager.get(project).store().getData().getLocales()) { - JBLabel localeLabel = new JBLabel(locale); - JBTextField localeText = new JBTextField(); - localeLabel.setLabelFor(localeText); - - valuePanel.add(localeLabel); - valuePanel.add(localeText); - valueTextFields.put(locale, localeText); - } - - JBScrollPane valuePane = new JBScrollPane(valuePanel); - valuePane.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(), - ResourceBundle.getBundle("messages").getString("translation.locales"))); - rootPanel.add(valuePane); + @Override + protected @NotNull DialogBuilder configure(@NotNull JComponent centerPanel) { DialogBuilder builder = new DialogBuilder(); - builder.setTitle(ResourceBundle.getBundle("messages").getString("action.add")); + builder.setTitle(bundle.getString("action.add")); builder.removeAllActions(); builder.addOkAction(); builder.addCancelAction(); - builder.setCenterPanel(rootPanel); - + builder.setCenterPanel(centerPanel); return builder; } -} \ No newline at end of file + + @Override + protected void handleExit(int exitCode) { + if(exitCode == DialogWrapper.OK_EXIT_CODE) { + InstanceManager.get(project).processUpdate(new TranslationCreate(getState())); + } + } +} diff --git a/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java b/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java index cc47e27..97cc5f5 100644 --- a/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java +++ b/src/main/java/de/marhali/easyi18n/dialog/EditDialog.java @@ -3,102 +3,53 @@ package de.marhali.easyi18n.dialog; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.ui.components.JBLabel; -import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.components.JBTextField; import de.marhali.easyi18n.InstanceManager; -import de.marhali.easyi18n.model.*; import de.marhali.easyi18n.dialog.descriptor.DeleteActionDescriptor; +import de.marhali.easyi18n.model.TranslationDelete; +import de.marhali.easyi18n.model.TranslationUpdate; +import de.marhali.easyi18n.model.translation.Translation; + +import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.border.EtchedBorder; -import java.awt.*; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; /** - * Edit translation dialog. + * Dialog to edit or delete an existing translation. * @author marhali */ -public class EditDialog { +public class EditDialog extends TranslationDialog { - private final Project project; - private final KeyPathConverter converter; - - private final KeyedTranslation origin; - - private JBTextField keyTextField; - private Map valueTextFields; - - public EditDialog(Project project, KeyedTranslation origin) { - this.project = project; - this.converter = new KeyPathConverter(project); - this.origin = origin; + /** + * Constructs a new edit dialog with the provided translation + * @param project Opened project + * @param origin Translation to edit + */ + public EditDialog(@NotNull Project project, @NotNull Translation origin) { + super(project, origin); } - public void showAndHandle() { - int code = prepare().show(); - - if(code == DialogWrapper.OK_EXIT_CODE) { // Edit - InstanceManager.get(project).processUpdate(new TranslationUpdate(origin, getChanges())); - } else if(code == DeleteActionDescriptor.EXIT_CODE) { // Delete - InstanceManager.get(project).processUpdate(new TranslationDelete(origin)); - } - } - - private KeyedTranslation getChanges() { - Translation translation = new Translation(); - - valueTextFields.forEach((k, v) -> { - if(!v.getText().isEmpty()) { - translation.put(k, v.getText()); - } - }); - - return new KeyedTranslation(converter.split(keyTextField.getText()), translation); - } - - private DialogBuilder prepare() { - JPanel rootPanel = new JPanel(); - rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS)); - - JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2,2)); - JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key")); - keyTextField = new JBTextField(this.converter.concat(this.origin.getKey())); - keyLabel.setLabelFor(keyTextField); - keyPanel.add(keyLabel); - keyPanel.add(keyTextField); - keyPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - rootPanel.add(keyPanel); - - JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2)); - valueTextFields = new HashMap<>(); - - for(String locale : InstanceManager.get(project).store().getData().getLocales()) { - JBLabel localeLabel = new JBLabel(locale); - JBTextField localeText = new JBTextField(this.origin.getTranslation().get(locale)); - localeLabel.setLabelFor(localeText); - - valuePanel.add(localeLabel); - valuePanel.add(localeText); - valueTextFields.put(locale, localeText); - } - - JBScrollPane valuePane = new JBScrollPane(valuePanel); - valuePane.setBorder(BorderFactory.createTitledBorder(new EtchedBorder(), - ResourceBundle.getBundle("messages").getString("translation.locales"))); - rootPanel.add(valuePane); - + @Override + protected @NotNull DialogBuilder configure(@NotNull JComponent centerPanel) { DialogBuilder builder = new DialogBuilder(); - builder.setTitle(ResourceBundle.getBundle("messages").getString("action.edit")); + builder.setTitle(bundle.getString("action.edit")); builder.removeAllActions(); builder.addCancelAction(); builder.addActionDescriptor(new DeleteActionDescriptor()); builder.addOkAction(); - builder.setCenterPanel(rootPanel); - + builder.setCenterPanel(centerPanel); return builder; } + + @Override + protected void handleExit(int exitCode) { + switch (exitCode) { + case DialogWrapper.OK_EXIT_CODE: + InstanceManager.get(project).processUpdate(new TranslationUpdate(origin, getState())); + break; + case DeleteActionDescriptor.EXIT_CODE: + InstanceManager.get(project).processUpdate(new TranslationDelete(origin)); + break; + } + } } \ No newline at end of file diff --git a/src/main/java/de/marhali/easyi18n/dialog/TranslationDialog.java b/src/main/java/de/marhali/easyi18n/dialog/TranslationDialog.java new file mode 100644 index 0000000..01cacd7 --- /dev/null +++ b/src/main/java/de/marhali/easyi18n/dialog/TranslationDialog.java @@ -0,0 +1,132 @@ +package de.marhali.easyi18n.dialog; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogBuilder; +import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.ui.FormBuilder; + +import de.marhali.easyi18n.InstanceManager; +import de.marhali.easyi18n.model.translation.KeyPath; +import de.marhali.easyi18n.model.translation.Translation; +import de.marhali.easyi18n.model.translation.TranslationValue; +import de.marhali.easyi18n.settings.ProjectSettings; +import de.marhali.easyi18n.settings.ProjectSettingsService; +import de.marhali.easyi18n.util.KeyPathConverter; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import java.awt.*; +import java.util.HashMap; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * Base for add and edit translation dialogs. + * @author marhali + */ +abstract class TranslationDialog { + + protected static final ResourceBundle bundle = ResourceBundle.getBundle("messages"); + + protected final @NotNull Project project; + protected final @NotNull ProjectSettings settings; + protected final @NotNull KeyPathConverter converter; + protected final @NotNull Translation origin; + + protected final JTextField keyField; + protected final JTextField descriptionField; + protected final Map localeValueFields; + + /** + * Constructs a new translation dialog. + * @param project Opened project + * @param origin Prefill translation + */ + protected TranslationDialog(@NotNull Project project, @NotNull Translation origin) { + this.project = project; + this.settings = ProjectSettingsService.get(project).getState(); + this.converter = new KeyPathConverter(settings); + this.origin = origin; + + // Fields + TranslationValue value = origin.getValue(); + + this.keyField = new JBTextField(converter.toString(origin.getKey())); + this.descriptionField = new JBTextField(value != null ? value.getDescription() : null); + this.localeValueFields = new HashMap<>(); + + for(String locale : InstanceManager.get(project).store().getData().getLocales()) { + localeValueFields.put(locale, new JBTextField(value != null ? value.get(locale) : null)); + } + } + + /** + * Implementation needs to configure the dialog. E.g. title, actions, ... + * The implementation needs to set the provided centerPanel as the view panel. + * @param centerPanel GUI to set on the dialog builder + * @return configured dialog builder + */ + protected abstract @NotNull DialogBuilder configure(@NotNull JComponent centerPanel); + + /** + * Implementation needs to handle exit + * @param exitCode See {@link com.intellij.openapi.ui.DialogWrapper} for exit codes + */ + protected abstract void handleExit(int exitCode); + + /** + * Opens the translation modal and applies the appropriate logic on modal close. + * Internally, the {@link #handleExit(int)} method will be called to determine finalization logic. + */ + public void showAndHandle() { + int exitCode = createDialog().show(); + handleExit(exitCode); + } + + /** + * Retrieve current modal state. + * @return Translation + */ + protected @NotNull Translation getState() { + KeyPath key = converter.fromString(keyField.getText()); + TranslationValue value = new TranslationValue(); + + value.setDescription(descriptionField.getText()); + + for(Map.Entry entry : localeValueFields.entrySet()) { + value.put(entry.getKey(), entry.getValue().getText()); + } + + return new Translation(key, value); + } + + private DialogBuilder createDialog() { + JPanel panel = FormBuilder.createFormBuilder() + .addLabeledComponent(bundle.getString("translation.key"), keyField, true) + .addLabeledComponent(bundle.getString("translation.description"), descriptionField, 6, true) + .addComponent(createLocalesPanel(), 12) + .getPanel(); + + panel.setMinimumSize(new Dimension(200, 150)); + + return configure(panel); + } + + private JComponent createLocalesPanel() { + FormBuilder builder = FormBuilder.createFormBuilder(); + + for(Map.Entry localeEntry : localeValueFields.entrySet()) { + builder.addLabeledComponent(localeEntry.getKey(), localeEntry.getValue(), 6, true); + } + + JScrollPane scrollPane = new JBScrollPane(builder.getPanel()); + + scrollPane.setBorder(BorderFactory.createTitledBorder( + new EtchedBorder(), bundle.getString("translation.locales"))); + + return scrollPane; + } +} \ No newline at end of file