/* * Copyright 2000-2012 JetBrains s.r.o. * * 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.openapi.roots.ui.configuration; import consulo.compiler.CompilerConfiguration; import com.intellij.icons.AllIcons; import com.intellij.ide.util.BrowseFilesListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.fileChooser.FileChooserFactory; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectStructureElementConfigurable; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement; import com.intellij.openapi.ui.DetailsComponent; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.FieldPanel; import com.intellij.ui.InsertPathAction; import consulo.roots.ui.configuration.WholeWestConfigurable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import consulo.annotations.RequiredDispatchThread; import javax.swing.*; import javax.swing.event.DocumentEvent; import java.awt.*; import java.io.IOException; /** * @author Eugene Zhuravlev * Date: Dec 15, 2003 */ public class ProjectConfigurable extends ProjectStructureElementConfigurable<Project> implements DetailsComponent.Facade, WholeWestConfigurable { private final Project myProject; private FieldPanel myProjectCompilerOutput; private JTextField myProjectName; private JPanel myPanel; private final StructureConfigurableContext myContext; private final ModulesConfigurator myModulesConfigurator; private boolean myFreeze = false; private DetailsComponent myDetailsComponent; private final GeneralProjectSettingsElement mySettingsElement; private final ConfigurationErrorsComponent myErrorsComponent; public ProjectConfigurable(Project project, final StructureConfigurableContext context, ModulesConfigurator configurator) { myProject = project; myContext = context; myErrorsComponent = new ConfigurationErrorsComponent(project); myModulesConfigurator = configurator; mySettingsElement = new GeneralProjectSettingsElement(context); final ProjectStructureDaemonAnalyzer daemonAnalyzer = context.getDaemonAnalyzer(); myModulesConfigurator.addAllModuleChangeListener(new ModuleEditor.ChangeListener() { @Override public void moduleStateChanged(ModifiableRootModel moduleRootModel) { daemonAnalyzer.queueUpdate(mySettingsElement); } }); init(); } @Override public ProjectStructureElement getProjectStructureElement() { return mySettingsElement; } @Override public DetailsComponent getDetailsComponent() { return myDetailsComponent; } @Override public JComponent createOptionsPanel() { myDetailsComponent = new DetailsComponent(false, false); myDetailsComponent.setContent(myPanel); myDetailsComponent.setText(getBannerSlogan()); return myDetailsComponent.getComponent(); } private void init() { myPanel = new JPanel(new VerticalFlowLayout(true, false)); final JPanel namePanel = new JPanel(new BorderLayout()); final JLabel label = new JLabel("<html><body><b>Project name:</b></body></html>", SwingConstants.LEFT); namePanel.add(label, BorderLayout.NORTH); myProjectName = new JTextField(); myProjectName.setColumns(40); final JPanel nameFieldPanel = new JPanel(); nameFieldPanel.setLayout(new BoxLayout(nameFieldPanel, BoxLayout.X_AXIS)); nameFieldPanel.add(Box.createHorizontalStrut(4)); nameFieldPanel.add(myProjectName); namePanel.add(nameFieldPanel, BorderLayout.CENTER); final JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT)); wrapper.add(namePanel); wrapper.setAlignmentX(0); myPanel.add(wrapper); myPanel.add(new JLabel(ProjectBundle.message("project.compiler.output"))); final JTextField textField = new JTextField(); final FileChooserDescriptor outputPathsChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); InsertPathAction.addTo(textField, outputPathsChooserDescriptor); outputPathsChooserDescriptor.setHideIgnored(false); BrowseFilesListener listener = new BrowseFilesListener(textField, "", ProjectBundle.message("project.compiler.output"), outputPathsChooserDescriptor); myProjectCompilerOutput = new FieldPanel(textField, null, null, listener, EmptyRunnable.getInstance()); FileChooserFactory.getInstance().installFileCompletion(myProjectCompilerOutput.getTextField(), outputPathsChooserDescriptor, true, null); myProjectCompilerOutput.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { if (myFreeze) return; myModulesConfigurator.processModuleCompilerOutputChanged(getCompilerOutputUrl()); } }); myPanel.add(myProjectCompilerOutput); myPanel.add(myErrorsComponent); } @RequiredDispatchThread @Override public void disposeUIResources() { } @RequiredDispatchThread @Override public void reset() { myFreeze = true; try { final String compilerOutput = CompilerConfiguration.getInstance(myProject).getCompilerOutputUrl(); if (compilerOutput != null) { myProjectCompilerOutput.setText(FileUtil.toSystemDependentName(VfsUtil.urlToPath(compilerOutput))); } if (myProjectName != null) { myProjectName.setText(myProject.getName()); } } finally { myFreeze = false; } myContext.getDaemonAnalyzer().queueUpdate(mySettingsElement); } @RequiredDispatchThread @Override public void apply() throws ConfigurationException { final CompilerConfiguration compilerProjectExtension = CompilerConfiguration.getInstance(myProject); if (myProjectName != null && StringUtil.isEmptyOrSpaces(myProjectName.getText())) { throw new ConfigurationException("Please, specify project name!"); } ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { // set the output path first so that handlers of RootsChanged event sent after JDK is set // would see the updated path String canonicalPath = myProjectCompilerOutput.getText(); if (canonicalPath != null && canonicalPath.length() > 0) { try { canonicalPath = FileUtil.resolveShortWindowsName(canonicalPath); } catch (IOException e) { //file doesn't exist yet } canonicalPath = FileUtil.toSystemIndependentName(canonicalPath); compilerProjectExtension.setCompilerOutputUrl(VfsUtil.pathToUrl(canonicalPath)); } else { compilerProjectExtension.setCompilerOutputUrl(null); } if (myProjectName != null) { ((ProjectEx)myProject).setProjectName(myProjectName.getText().trim()); if (myDetailsComponent != null) myDetailsComponent.setText(getBannerSlogan()); } } }); } @Override public void setDisplayName(final String name) { //do nothing } @Override public Project getEditableObject() { return myProject; } @Override public String getBannerSlogan() { return ProjectBundle.message("project.roots.project.banner.text", myProject.getName()); } @Override public String getDisplayName() { return ProjectBundle.message("project.roots.project.display.name"); } @Override public Icon getIcon(boolean open) { return AllIcons.Nodes.ProjectTab; } @Override @Nullable @NonNls public String getHelpTopic() { return "reference.settingsdialog.project.structure.general"; } @RequiredDispatchThread @Override @SuppressWarnings({"SimplifiableIfStatement"}) public boolean isModified() { final String compilerOutput = CompilerConfiguration.getInstance(myProject).getCompilerOutputUrl(); if (!Comparing.strEqual(FileUtil.toSystemIndependentName(VfsUtil.urlToPath(compilerOutput)), FileUtil.toSystemIndependentName(myProjectCompilerOutput.getText()))) { return true; } if (myProjectName != null) { if (!myProjectName.getText().trim().equals(myProject.getName())) return true; } return false; } public String getCompilerOutputUrl() { return VfsUtil.pathToUrl(myProjectCompilerOutput.getText().trim()); } @NotNull @Override public Couple<JComponent> createSplitterComponents() { return Couple.of(new JPanel(), createComponent()); } }