/* * Copyright 2000-2013 JetBrains s.r.o. * Copyright 2014-2014 AS3Boyan * Copyright 2014-2014 Elias Ku * * 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 com.intellij.plugins.haxe.ide.projectStructure.ui; import com.intellij.ide.actions.ShowSettingsUtilImpl; import com.intellij.ide.util.TreeFileChooser; import com.intellij.ide.util.TreeFileChooserFactory; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.openapi.options.ex.SingleConfigurableEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.impl.DirectoryIndex; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.plugins.haxe.HaxeBundle; import com.intellij.plugins.haxe.HaxeFileType; import com.intellij.plugins.haxe.config.*; import com.intellij.plugins.haxe.ide.module.HaxeModuleSettings; import com.intellij.plugins.haxe.ide.projectStructure.HaxeModuleConfigurationExtensionPoint; import com.intellij.psi.PsiFile; import com.intellij.ui.RawCommandLineEditor; import com.intellij.ui.components.JBRadioButton; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; /** * @author: Fedor.Korotkov */ public class HaxeConfigurationEditor { private JPanel myMainPanel; private TextFieldWithBrowseButton myMainClassFieldWithButton; private RawCommandLineEditor myAppArguments; private JComboBox myTargetComboBox; private JCheckBox myExcludeFromCompilationCheckBox; private JLabel myTargetLabel; private JLabel myMainClassLabel; private JLabel myParametersLabel; private JTextField myOutputFileNameTextField; private TextFieldWithBrowseButton myFolderTextField; private JLabel myFolderLabel; private JPanel myAdditionalComponentPanel; private TextFieldWithBrowseButton myHxmlFileChooserTextField; private JBRadioButton myHxmlFileRadioButton; private JBRadioButton myNmmlFileRadioButton; private JBRadioButton myOpenFLFileRadioButton; private JBRadioButton myUserPropertiesRadioButton; private JPanel myCompilerOptions; private JPanel myCommonPanel; private JTextField myDefinedMacroses; private JButton myEditMacrosesButton; private JPanel myHxmlFileChooserPanel; private RawCommandLineEditor myNMEArguments; private TextFieldWithBrowseButton myNMEFileChooserTextField; private JPanel myNMEFilePanel; private JPanel myOpenFLFilePanel; private JPanel myBuildFilePanel; private JPanel myCompilerOptionsWrapper; private TextFieldWithBrowseButton myOpenFLFileChooserTextField; private RawCommandLineEditor myOpenFLArgumentTextField; private HaxeTarget selectedHaxeTarget = HaxeTarget.NEKO; private NMETarget selectedNmeTarget = NMETarget.FLASH; private OpenFLTarget selectedOpenFLTarget = OpenFLTarget.FLASH; private final Module myModule; private final CompilerModuleExtension myExtension; private final List<UnnamedConfigurable> configurables = new ArrayList<UnnamedConfigurable>(); public HaxeConfigurationEditor(Module module, CompilerModuleExtension extension) { myModule = module; myExtension = extension; addActionListeners(); initExtensions(); myMainClassLabel.setLabelFor(myMainClassFieldWithButton.getTextField()); myParametersLabel.setLabelFor(myAppArguments.getTextField()); myFolderLabel.setLabelFor(myFolderTextField.getTextField()); ButtonGroup group = new ButtonGroup(); group.add(myHxmlFileRadioButton); group.add(myNmmlFileRadioButton); group.add(myUserPropertiesRadioButton); group.add(myOpenFLFileRadioButton); } private void addActionListeners() { myMainClassFieldWithButton.getButton().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { TreeFileChooser fileChooser = TreeFileChooserFactory.getInstance(myModule.getProject()).createFileChooser( HaxeBundle.message("choose.haxe.main.class"), null, HaxeFileType.HAXE_FILE_TYPE, new TreeFileChooser.PsiFileFilter() { public boolean accept(PsiFile file) { return true; } }); fileChooser.showDialog(); PsiFile selectedFile = fileChooser.getSelectedFile(); if (selectedFile != null) { setChosenFile(selectedFile.getVirtualFile()); } } }); myFolderTextField.getButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final VirtualFile folder = FileChooser.chooseFile(FileChooserDescriptorFactory.createSingleFolderDescriptor(), myModule.getProject(), null); if (folder != null) { myFolderTextField.setText(FileUtil.toSystemDependentName(folder.getPath())); } } }); myTargetComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (myTargetComboBox.getSelectedItem() instanceof HaxeTarget) { selectedHaxeTarget = (HaxeTarget)myTargetComboBox.getSelectedItem(); } if (myTargetComboBox.getSelectedItem() instanceof NMETarget) { selectedNmeTarget = (NMETarget)myTargetComboBox.getSelectedItem(); } if (myTargetComboBox.getSelectedItem() instanceof OpenFLTarget) { selectedOpenFLTarget = (OpenFLTarget)myTargetComboBox.getSelectedItem(); } if (!myOutputFileNameTextField.getText().isEmpty()) { myOutputFileNameTextField.setText(getCurrentExtension(FileUtil.getNameWithoutExtension(myOutputFileNameTextField.getText()))); } } }); final ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateComponents(); updateTargetCombo(); } }; myHxmlFileRadioButton.addActionListener(listener); myNmmlFileRadioButton.addActionListener(listener); myUserPropertiesRadioButton.addActionListener(listener); myOpenFLFileRadioButton.addActionListener(listener); ActionListener fileChooserListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final VirtualFile moduleFile = myModule.getModuleFile(); assert moduleFile != null; final boolean isNMML = myNmmlFileRadioButton.isSelected(); final boolean isOpenFL = myOpenFLFileRadioButton.isSelected(); final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, true, false, false) { public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { return super.isFileVisible(file, showHiddenFiles) && (file.isDirectory() || (!isNMML && !isOpenFL && "hxml".equalsIgnoreCase(file.getExtension())) || (isNMML && "nmml".equalsIgnoreCase(file.getExtension())) || (isOpenFL && "xml".equalsIgnoreCase(file.getExtension())) || (isOpenFL && "lime".equalsIgnoreCase(file.getExtension())) ); } }; final VirtualFile file = FileChooser.chooseFile(descriptor, getMainPanel(), null, moduleFile.getParent()); if (file != null) { String path = FileUtil.toSystemIndependentName(file.getPath()); if (isNMML) { myNMEFileChooserTextField.setText(path); } else if(isOpenFL) { myOpenFLFileChooserTextField.setText(path); } else { myHxmlFileChooserTextField.setText(path); } updateComponents(); } } }; myHxmlFileChooserTextField.getButton().addActionListener(fileChooserListener); myNMEFileChooserTextField.getButton().addActionListener(fileChooserListener); myOpenFLFileChooserTextField.getButton().addActionListener(fileChooserListener); myEditMacrosesButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final Project project = myModule.getProject(); final HaxeSettingsConfigurable configurable = new HaxeSettingsConfigurable(project); final SingleConfigurableEditor editor = new SingleConfigurableEditor( project, configurable, ShowSettingsUtilImpl.createDimensionKey(configurable), false ); editor.show(); updateMacroses(); } }); } private void updateComponents() { updateUserProperties(); updateFileChooser(); updateMacroses(); } private void updateMacroses() { final String[] userCompilerDefinitions = HaxeProjectSettings.getInstance(myModule.getProject()).getUserCompilerDefinitions(); myDefinedMacroses.setText(StringUtil.join(userCompilerDefinitions, ",")); } private void updateFileChooser() { boolean containsHxml = false; boolean containsNME = false; boolean containsOpenFL = false; Component[] components = myBuildFilePanel.getComponents(); for (Component component : components) { if (component == myHxmlFileChooserPanel) { containsHxml = true; } if (component == myNMEFilePanel) { containsNME = true; } if (component == myOpenFLFilePanel) { containsOpenFL = true; } } if (!myHxmlFileRadioButton.isSelected() && containsHxml) { myBuildFilePanel.remove(myHxmlFileChooserPanel); } if (!myNmmlFileRadioButton.isSelected() && containsNME) { myBuildFilePanel.remove(myNMEFilePanel); } if (!myOpenFLFileRadioButton.isSelected() && containsOpenFL) { myBuildFilePanel.remove(myOpenFLFilePanel); myBuildFilePanel.remove(myOpenFLFileChooserTextField); } final GridConstraints constraints = new GridConstraints(); constraints.setRow(0); constraints.setFill(GridConstraints.FILL_HORIZONTAL); if (myHxmlFileRadioButton.isSelected() && !containsHxml) { myBuildFilePanel.add(myHxmlFileChooserPanel, constraints); } if (myNmmlFileRadioButton.isSelected() && !containsNME) { myBuildFilePanel.add(myNMEFilePanel, constraints); } if (myOpenFLFileRadioButton.isSelected() && !containsOpenFL) { myBuildFilePanel.add(myOpenFLFilePanel, constraints); } myBuildFilePanel.repaint(); } private void updateUserProperties() { boolean contains = false; Component[] components = myCompilerOptionsWrapper.getComponents(); for (Component component : components) { if (component == myCompilerOptions) { contains = true; break; } } if (myUserPropertiesRadioButton.isSelected() && !contains) { final GridConstraints constraints = new GridConstraints(); constraints.setRow(0); constraints.setFill(GridConstraints.FILL_HORIZONTAL); myCompilerOptionsWrapper.add(myCompilerOptions, constraints); } else if (!myUserPropertiesRadioButton.isSelected() && contains) { myCompilerOptionsWrapper.remove(myCompilerOptions); } } private void updateTargetCombo() { ((DefaultComboBoxModel)myTargetComboBox.getModel()).removeAllElements(); if (myNmmlFileRadioButton.isSelected()) { NMETarget.initCombo((DefaultComboBoxModel)myTargetComboBox.getModel()); myTargetComboBox.setSelectedItem(selectedNmeTarget); } else if (myOpenFLFileRadioButton.isSelected()) { OpenFLTarget.initCombo((DefaultComboBoxModel)myTargetComboBox.getModel()); myTargetComboBox.setSelectedItem(selectedOpenFLTarget); } else { HaxeTarget.initCombo((DefaultComboBoxModel)myTargetComboBox.getModel()); myTargetComboBox.setSelectedItem(selectedHaxeTarget); } } private void initExtensions() { final HaxeModuleSettings settings = HaxeModuleSettings.getInstance(myModule); final HaxeModuleConfigurationExtensionPoint[] extensionPoints = HaxeModuleConfigurationExtensionPoint.EP_NAME.getExtensions(); if (extensionPoints.length > 0) { final GridLayoutManager layoutManager = new GridLayoutManager(extensionPoints.length, 1); myAdditionalComponentPanel.setLayout(layoutManager); } for (int i = 0; i < extensionPoints.length; i++) { HaxeModuleConfigurationExtensionPoint extensionPoint = extensionPoints[i]; final GridConstraints gridConstraints = new GridConstraints(); gridConstraints.setFill(GridConstraints.FILL_HORIZONTAL); gridConstraints.setRow(i); final UnnamedConfigurable configurable = extensionPoint.createConfigurable(settings); configurables.add(configurable); myAdditionalComponentPanel.add(configurable.createComponent(), gridConstraints); } } private void setChosenFile(VirtualFile virtualFile) { VirtualFile parent = virtualFile.getParent(); String qualifier = parent == null ? null : DirectoryIndex.getInstance(myModule.getProject()).getPackageName(parent); qualifier = qualifier != null && qualifier.length() != 0 ? qualifier + '.' : ""; myMainClassFieldWithButton.setText(qualifier + FileUtil.getNameWithoutExtension(virtualFile.getName())); } private String getCurrentExtension(String fileName) { if (selectedHaxeTarget != null) { return selectedHaxeTarget.getTargetFileNameWithExtension(fileName); } return fileName; } public boolean isModified() { final HaxeModuleSettings settings = HaxeModuleSettings.getInstance(myModule); assert settings != null; final String url = myExtension.getCompilerOutputUrl(); final String urlCandidate = VfsUtilCore.pathToUrl(myFolderTextField.getText()); boolean result = !urlCandidate.equals(url); result = result || settings.getNmeTarget() != selectedNmeTarget; result = result || !FileUtil.toSystemIndependentName(myNMEFileChooserTextField.getText()).equals(settings.getNmmlPath()); result = result || settings.getOpenFLTarget() != selectedOpenFLTarget; result = result || !settings.getMainClass().equals(myMainClassFieldWithButton.getText()); result = result || settings.getHaxeTarget() != selectedHaxeTarget; result = result || !FileUtil.toSystemIndependentName(myHxmlFileChooserTextField.getText()).equals(settings.getHxmlPath()); result = result || !FileUtil.toSystemIndependentName(myOpenFLFileChooserTextField.getText()).equals(settings.getOpenFLPath()); result = result || !settings.getArguments().equals(myAppArguments.getText()); result = result || !settings.getNmeFlags().equals(myNMEArguments.getText()); result = result || !settings.getOpenFLFlags().equals(myOpenFLArgumentTextField.getText()); result = result || (settings.isExcludeFromCompilation() ^ myExcludeFromCompilationCheckBox.isSelected()); result = result || !settings.getOutputFileName().equals(myOutputFileNameTextField.getText()); result = result || !settings.getOutputFolder().equals(myFolderTextField.getText()); result = result || getCurrentBuildConfig() != settings.getBuildConfig(); for (UnnamedConfigurable configurable : configurables) { result = result || configurable.isModified(); } return result; } public void reset() { final HaxeModuleSettings settings = HaxeModuleSettings.getInstance(myModule); assert settings != null; myMainClassFieldWithButton.setText(settings.getMainClass()); myAppArguments.setText(settings.getArguments()); selectedHaxeTarget = settings.getHaxeTarget(); selectedNmeTarget = settings.getNmeTarget(); selectedOpenFLTarget = settings.getOpenFLTarget(); myExcludeFromCompilationCheckBox.setSelected(settings.isExcludeFromCompilation()); myOutputFileNameTextField.setText(settings.getOutputFileName()); myFolderTextField.setText(settings.getOutputFolder()); for (UnnamedConfigurable configurable : configurables) { configurable.reset(); } final String url = myExtension.getCompilerOutputUrl(); myFolderTextField.setText(VfsUtil.urlToPath(url)); myHxmlFileChooserTextField.setText(settings.getHxmlPath()); myOpenFLFileChooserTextField.setText(settings.getOpenFLPath()); myNMEFileChooserTextField.setText(settings.getNmmlPath()); myNMEArguments.setText(settings.getNmeFlags()); myOpenFLArgumentTextField.setText(settings.getOpenFLFlags()); myHxmlFileRadioButton.setSelected(settings.isUseHxmlToBuild()); myNmmlFileRadioButton.setSelected(settings.isUseNmmlToBuild()); myUserPropertiesRadioButton.setSelected(settings.isUseUserPropertiesToBuild()); myOpenFLFileRadioButton.setSelected(settings.isUseOpenFLToBuild()); updateComponents(); updateTargetCombo(); } public void apply() { final HaxeModuleSettings settings = HaxeModuleSettings.getInstance(myModule); assert settings != null; settings.setMainClass(myMainClassFieldWithButton.getText()); settings.setArguments(myAppArguments.getText()); settings.setNmeFlags(myNMEArguments.getText()); settings.setOpenFLFlags(myOpenFLArgumentTextField.getText()); if (myNmmlFileRadioButton.isSelected()) { settings.setNmeTarget((NMETarget)myTargetComboBox.getSelectedItem()); } else if (myOpenFLFileRadioButton.isSelected()) { settings.setOpenFLTarget((OpenFLTarget)myTargetComboBox.getSelectedItem()); } else { settings.setHaxeTarget((HaxeTarget)myTargetComboBox.getSelectedItem()); } settings.setExcludeFromCompilation(myExcludeFromCompilationCheckBox.isSelected()); settings.setOutputFileName(myOutputFileNameTextField.getText()); settings.setOutputFolder(myFolderTextField.getText()); settings.setHxmlPath(FileUtil.toSystemIndependentName(myHxmlFileChooserTextField.getText())); settings.setOpenFLPath(FileUtil.toSystemIndependentName(myOpenFLFileChooserTextField.getText())); settings.setNmmlPath(FileUtil.toSystemIndependentName(myNMEFileChooserTextField.getText())); settings.setBuildConfig(getCurrentBuildConfig()); for (UnnamedConfigurable configurable : configurables) { try { configurable.apply(); } catch (ConfigurationException ignored) { } } final String url = myExtension.getCompilerOutputUrl(); final String urlCandidate = VfsUtil.pathToUrl(myFolderTextField.getText()); if (!urlCandidate.equals(url)) { myExtension.setCompilerOutputPath(urlCandidate); myExtension.commit(); } } private int getCurrentBuildConfig() { int buildConfig = HaxeModuleSettings.USE_PROPERTIES; if (myHxmlFileRadioButton.isSelected()) { buildConfig = HaxeModuleSettings.USE_HXML; } else if (myNmmlFileRadioButton.isSelected()) { buildConfig = HaxeModuleSettings.USE_NMML; } else if (myOpenFLFileRadioButton.isSelected()) { buildConfig = HaxeModuleSettings.USE_OPENFL; } return buildConfig; } public JComponent getMainPanel() { return myMainPanel; } }