blob: 5a933ab18e42ebd2424452c08568ee936a177070 [file] [log] [blame]
/*
* Copyright 2000-2013 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.externalSystem.service.settings;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListener;
import com.intellij.openapi.externalSystem.util.*;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.io.File;
import java.util.Comparator;
import java.util.List;
/**
* Base class that simplifies external system settings management.
* <p/>
* The general idea is to provide a control which looks like below:
* <pre>
* ----------------------------------------------
* | linked external projects list |
* |----------------------------------------------
* | linked project-specific settings |
* |----------------------------------------------
* | external system-wide settings (optional) |
----------------------------------------------
* </pre>
*
* @author Denis Zhdanov
* @since 4/30/13 12:50 PM
*/
public abstract class AbstractExternalSystemConfigurable<
ProjectSettings extends ExternalProjectSettings,
L extends ExternalSystemSettingsListener<ProjectSettings>,
SystemSettings extends AbstractExternalSystemSettings<SystemSettings, ProjectSettings, L>
> implements SearchableConfigurable, Configurable.NoScroll
{
@NotNull private final List<ExternalSystemSettingsControl<ProjectSettings>> myProjectSettingsControls = ContainerUtilRt.newArrayList();
@NotNull private final ProjectSystemId myExternalSystemId;
@NotNull private final Project myProject;
@Nullable private ExternalSystemSettingsControl<SystemSettings> mySystemSettingsControl;
@Nullable private ExternalSystemSettingsControl<ProjectSettings> myActiveProjectSettingsControl;
private PaintAwarePanel myComponent;
private JBList myProjectsList;
private DefaultListModel myProjectsModel;
protected AbstractExternalSystemConfigurable(@NotNull Project project, @NotNull ProjectSystemId externalSystemId) {
myProject = project;
myExternalSystemId = externalSystemId;
}
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
@Nls
@Override
public String getDisplayName() {
return myExternalSystemId.getReadableName();
}
@Nullable
@Override
public JComponent createComponent() {
if (myComponent == null) {
myComponent = new PaintAwarePanel(new GridBagLayout());
SystemSettings settings = getSettings();
prepareProjectSettings(settings);
prepareSystemSettings(settings);
ExternalSystemUiUtil.fillBottom(myComponent);
}
return myComponent;
}
@SuppressWarnings("unchecked")
@NotNull
private SystemSettings getSettings() {
ExternalSystemManager<ProjectSettings, L, SystemSettings, ?, ?> manager =
(ExternalSystemManager<ProjectSettings, L, SystemSettings, ?, ?>)ExternalSystemApiUtil.getManager(myExternalSystemId);
assert manager != null;
return manager.getSettingsProvider().fun(myProject);
}
@SuppressWarnings("unchecked")
private void prepareProjectSettings(@NotNull SystemSettings s) {
myProjectsModel = new DefaultListModel();
myProjectsList = new JBList(myProjectsModel);
myProjectsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
addTitle(ExternalSystemBundle.message("settings.title.linked.projects", myExternalSystemId.getReadableName()));
myComponent.add(new JBScrollPane(myProjectsList), ExternalSystemUiUtil.getFillLineConstraints(1));
addTitle(ExternalSystemBundle.message("settings.title.project.settings"));
List<ProjectSettings> settings = ContainerUtilRt.newArrayList(s.getLinkedProjectsSettings());
myProjectsList.setVisibleRowCount(Math.max(3, Math.min(5, settings.size())));
ContainerUtil.sort(settings, new Comparator<ProjectSettings>() {
@Override
public int compare(ProjectSettings s1, ProjectSettings s2) {
return getProjectName(s1.getExternalProjectPath()).compareTo(getProjectName(s2.getExternalProjectPath()));
}
});
myProjectSettingsControls.clear();
for (ProjectSettings setting : settings) {
ExternalSystemSettingsControl<ProjectSettings> control = createProjectSettingsControl(setting);
control.fillUi(myComponent, 1);
myProjectsModel.addElement(getProjectName(setting.getExternalProjectPath()));
myProjectSettingsControls.add(control);
control.showUi(false);
}
myProjectsList.addListSelectionListener(new ListSelectionListener() {
@SuppressWarnings("unchecked")
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
int i = myProjectsList.getSelectedIndex();
if (i < 0) {
return;
}
if (myActiveProjectSettingsControl != null) {
myActiveProjectSettingsControl.showUi(false);
}
myActiveProjectSettingsControl = myProjectSettingsControls.get(i);
myActiveProjectSettingsControl.showUi(true);
}
});
if (!myProjectsModel.isEmpty()) {
myProjectsList.setSelectedIndex(0);
}
}
private void addTitle(@NotNull String title) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(IdeBorderFactory.createTitledBorder(title, false, new Insets(ExternalSystemUiUtil.INSETS, 0, 0, 0)));
myComponent.add(panel, ExternalSystemUiUtil.getFillLineConstraints(0));
}
/**
* Creates a control for managing given project settings.
*
* @param settings target external project settings
* @return control for managing given project settings
*/
@NotNull
protected abstract ExternalSystemSettingsControl<ProjectSettings> createProjectSettingsControl(@NotNull ProjectSettings settings);
@SuppressWarnings("MethodMayBeStatic")
@NotNull
protected String getProjectName(@NotNull String path) {
File file = new File(path);
return file.isDirectory() || file.getParentFile() == null ? file.getName() : file.getParentFile().getName();
}
private void prepareSystemSettings(@NotNull SystemSettings s) {
mySystemSettingsControl = createSystemSettingsControl(s);
if (mySystemSettingsControl != null) {
addTitle(ExternalSystemBundle.message("settings.title.system.settings", myExternalSystemId.getReadableName()));
mySystemSettingsControl.fillUi(myComponent, 1);
}
}
/**
* Creates a control for managing given system-level settings (if any).
*
* @param settings target system settings
* @return a control for managing given system-level settings;
* <code>null</code> if current external system doesn't have system-level settings (only project-level settings)
*/
@Nullable
protected abstract ExternalSystemSettingsControl<SystemSettings> createSystemSettingsControl(@NotNull SystemSettings settings);
@Override
public boolean isModified() {
for (ExternalSystemSettingsControl<ProjectSettings> control : myProjectSettingsControls) {
if (control.isModified()) {
return true;
}
}
return mySystemSettingsControl != null && mySystemSettingsControl.isModified();
}
@Override
public void apply() throws ConfigurationException {
SystemSettings systemSettings = getSettings();
L publisher = systemSettings.getPublisher();
publisher.onBulkChangeStart();
try {
List<ProjectSettings> projectSettings = ContainerUtilRt.newArrayList();
for (ExternalSystemSettingsControl<ProjectSettings> control : myProjectSettingsControls) {
ProjectSettings s = newProjectSettings();
control.apply(s);
projectSettings.add(s);
}
systemSettings.setLinkedProjectsSettings(projectSettings);
for (ExternalSystemSettingsControl<ProjectSettings> control : myProjectSettingsControls) {
if(control instanceof AbstractExternalProjectSettingsControl){
AbstractExternalProjectSettingsControl.class.cast(control).updateInitialSettings();
}
}
if (mySystemSettingsControl != null) {
mySystemSettingsControl.apply(systemSettings);
}
}
finally {
publisher.onBulkChangeEnd();
}
}
/**
* @return new empty project-level settings object
*/
@NotNull
protected abstract ProjectSettings newProjectSettings();
@Override
public void reset() {
for (ExternalSystemSettingsControl<ProjectSettings> control : myProjectSettingsControls) {
control.reset();
}
if (mySystemSettingsControl != null) {
mySystemSettingsControl.reset();
}
}
@Override
public void disposeUIResources() {
for (ExternalSystemSettingsControl<ProjectSettings> control : myProjectSettingsControls) {
control.disposeUIResources();
}
myProjectSettingsControls.clear();
myComponent = null;
myProjectsList = null;
myProjectsModel = null;
mySystemSettingsControl = null;
}
}