/*
* Copyright 2010 The WicketForge-Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package wicketforge.action.ui;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaDirectoryService;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiPackage;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import wicketforge.Constants;
import wicketforge.search.PropertiesIndex;
import wicketforge.util.WicketFileUtil;
import wicketforge.util.WicketFilenameUtil;
import wicketforge.util.WicketPsiUtil;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
public class ExtractPropertiesDialog extends DialogWrapper {
private JPanel contentPane;
private JTextField propertyKeyTextField;
private JTextArea propertyValueTextArea;
private JComboBox propertiesFileComboBox;
private JCheckBox chooseDifferentDestinationFolderCheckBox;
private JPanel chooseDifferentDestinationFolderPanel;
private Project project;
private Module module;
private ActionRunnable actionRunnable;
private PsiClass componentClass;
private PsiDirectory destinationDirectory;
private PsiPackage psiPackage;
public ExtractPropertiesDialog(@NotNull Project project, @NotNull ActionRunnable actionRunnable, @NotNull String title, @NotNull PsiClass componentClass, @NotNull PsiDirectory directory, @NotNull String text) {
super(project, false);
this.project = project;
this.actionRunnable = actionRunnable;
this.componentClass = componentClass;
this.destinationDirectory = directory;
this.module = ModuleUtil.findModuleForPsiElement(directory);
this.psiPackage = JavaDirectoryService.getInstance().getPackage(directory);
setResizable(true);
setModal(true);
setTitle(title);
propertyValueTextArea.setText(text);
addPropertiesFilesOptions();
init();
}
@Override
protected void init() {
super.init();
// set a simple key from text value
StringBuilder sb = new StringBuilder();
for (String word : StringUtil.getWordsIn(propertyValueTextArea.getText())) {
if (word.length() > 1 && StringUtil.containsAlphaCharacters(word)) {
sb.append(StringUtil.capitalize(word));
if (sb.length() > 100) {
break;
}
}
}
propertyKeyTextField.setText(sb.toString());
// if we have only 1 destination, we dont offer a different folder selection
if (WicketFileUtil.getResourceRoots(module).length < 2) {
chooseDifferentDestinationFolderPanel.setVisible(false);
}
}
@Override
protected JComponent createCenterPanel() {
return contentPane;
}
@Override
public JComponent getPreferredFocusedComponent() {
return propertyKeyTextField;
}
private void addPropertiesFilesOptions() {
List<Object> data = new ArrayList<Object>();
{ // find component class properties file
PropertiesFile propertiesFile = PropertiesIndex.getBaseFile(componentClass);
if (propertiesFile == null) {
data.add(new NewPropertiesFileInfo(componentClass, Constants.PropertiesType.PROPERTIES));
data.add(new NewPropertiesFileInfo(componentClass, Constants.PropertiesType.XML));
} else {
data.add(propertiesFile);
}
}
{ // find and add application properties file
PsiClass appClass = WicketPsiUtil.findWicketApplicationClass(project);
if (appClass != null) {
PropertiesFile propertiesFile = PropertiesIndex.getBaseFile(appClass);
if (propertiesFile != null) {
data.add(propertiesFile);
}
}
}
propertiesFileComboBox.setModel(new DefaultComboBoxModel(data.toArray(new Object[data.size()])));
propertiesFileComboBox.setRenderer(new PropertiesFileComboBoxRenderer());
propertiesFileComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// if a properties file is selected, then there is nothing to create so no different destination selectable...
chooseDifferentDestinationFolderCheckBox.setEnabled(!(propertiesFileComboBox.getSelectedItem() instanceof PropertiesFile));
}
});
chooseDifferentDestinationFolderCheckBox.setEnabled(!(propertiesFileComboBox.getSelectedItem() instanceof PropertiesFile));
}
private boolean validateInput() {
String key = propertyKeyTextField.getText();
if (key == null || key.length() == 0) {
setErrorText("Property key cannot be null");
return false;
}
String value = propertyValueTextArea.getText();
if (value == null || value.length() == 0) {
setErrorText("Property value cannot be null");
return false;
}
Object o = propertiesFileComboBox.getSelectedItem();
if (o instanceof PropertiesFile) {
for (IProperty prop : ((PropertiesFile) o).getProperties()) {
if (key.equals(prop.getKey())) {
setErrorText(String.format("Property key '%s' already in use", key));
return false;
}
}
}
setErrorText(null);
return true;
}
@Override
protected void doOKAction() {
Object selectedItem = propertiesFileComboBox.getSelectedItem();
// if we dont have any properties file (we will create one) -> ask for destination
if (module != null && psiPackage != null && selectedItem instanceof NewPropertiesFileInfo && chooseDifferentDestinationFolderCheckBox.isSelected()) {
PsiDirectory directory = WicketFileUtil.selectTargetDirectory(psiPackage.getQualifiedName(), project, module);
if (directory == null) {
return; // aborted
}
destinationDirectory = directory;
}
if (validateInput() && actionRunnable.run(selectedItem, destinationDirectory, propertyKeyTextField.getText(), propertyValueTextArea.getText())) {
super.doOKAction();
}
}
private static class PropertiesFileComboBoxRenderer extends ColoredListCellRenderer {
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
if (value instanceof PropertiesFile) {
append(((PropertiesFile) value).getName());
} else if (value instanceof NewPropertiesFileInfo) {
append(((NewPropertiesFileInfo) value).getName());
append(" [new]", SimpleTextAttributes.GRAYED_ATTRIBUTES);
}
}
}
public static class NewPropertiesFileInfo {
private Constants.PropertiesType propertiesType;
private String name;
public NewPropertiesFileInfo(PsiClass componentClass, Constants.PropertiesType propertiesType) {
this.propertiesType = propertiesType;
this.name = WicketFilenameUtil.getPropertiesFilename(componentClass, propertiesType);
}
public Constants.PropertiesType getPropertiesType() {
return propertiesType;
}
public String getName() {
return name;
}
}
public static interface ActionRunnable {
/**
* @param selectedItem PropertiesFile or NewPropertiesFileInfo
*/
boolean run(@Nullable Object selectedItem, @NotNull PsiDirectory destinationDirectory, @NotNull String key, @NotNull String value);
}
}