blob: 191c0f79b25cad825d58545a81395cccf96138e8 [file] [log] [blame]
/*
* Copyright 2000-2014 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.execution.impl;
import com.intellij.execution.BeforeRunTask;
import com.intellij.execution.BeforeRunTaskProvider;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.UnknownRunConfiguration;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
/**
* @author Vassiliy Kudryashov
*/
class BeforeRunStepsPanel extends JPanel {
private final JCheckBox myShowSettingsBeforeRunCheckBox;
private final JBList myList;
private final CollectionListModel<BeforeRunTask> myModel;
private RunConfiguration myRunConfiguration;
private final List<BeforeRunTask> originalTasks = new ArrayList<BeforeRunTask>();
private final StepsBeforeRunListener myListener;
private final JPanel myPanel;
BeforeRunStepsPanel(StepsBeforeRunListener listener) {
myListener = listener;
myModel = new CollectionListModel<BeforeRunTask>();
myList = new JBList(myModel);
myList.getEmptyText().setText(ExecutionBundle.message("before.launch.panel.empty"));
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setCellRenderer(new MyListCellRenderer());
myModel.addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent e) {
adjustVisibleRowCount();
updateText();
}
@Override
public void intervalRemoved(ListDataEvent e) {
adjustVisibleRowCount();
updateText();
}
@Override
public void contentsChanged(ListDataEvent e) {
}
private void adjustVisibleRowCount() {
myList.setVisibleRowCount(Math.max(4, Math.min(8, myModel.getSize())));
}
});
ToolbarDecorator myDecorator = ToolbarDecorator.createDecorator(myList);
if (!SystemInfo.isMac) {
myDecorator.setAsUsualTopToolbar();
}
myDecorator.setEditAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
int index = myList.getSelectedIndex();
if (index == -1)
return;
Pair<BeforeRunTask, BeforeRunTaskProvider<BeforeRunTask>> selection = getSelection();
if (selection == null)
return;
BeforeRunTask task = selection.getFirst();
BeforeRunTaskProvider<BeforeRunTask> provider = selection.getSecond();
if (provider.configureTask(myRunConfiguration, task)) {
myModel.setElementAt(task, index);
updateText();
}
}
});
myDecorator.setEditActionUpdater(new AnActionButtonUpdater() {
@Override
public boolean isEnabled(AnActionEvent e) {
Pair<BeforeRunTask, BeforeRunTaskProvider<BeforeRunTask>> selection = getSelection();
return selection != null && selection.getSecond().isConfigurable();
}
});
myDecorator.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
doAddAction(button);
}
});
myDecorator.setAddActionUpdater(new AnActionButtonUpdater() {
@Override
public boolean isEnabled(AnActionEvent e) {
return checkBeforeRunTasksAbility(true);
}
});
myShowSettingsBeforeRunCheckBox = new JCheckBox(ExecutionBundle.message("configuration.edit.before.run"));
myShowSettingsBeforeRunCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateText();
}
});
myPanel = myDecorator.createPanel();
setLayout(new BorderLayout());
add(myPanel, BorderLayout.CENTER);
add(myShowSettingsBeforeRunCheckBox, BorderLayout.SOUTH);
}
@Nullable
private Pair<BeforeRunTask, BeforeRunTaskProvider<BeforeRunTask>> getSelection() {
final int index = myList.getSelectedIndex();
if (index ==-1)
return null;
BeforeRunTask task = myModel.getElementAt(index);
Key providerId = task.getProviderId();
BeforeRunTaskProvider<BeforeRunTask> provider = BeforeRunTaskProvider.getProvider(myRunConfiguration.getProject(), providerId);
return provider != null ? Pair.create(task, provider) : null;
}
void doReset(RunnerAndConfigurationSettings settings) {
myRunConfiguration = settings.getConfiguration();
originalTasks.clear();
RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myRunConfiguration.getProject());
originalTasks.addAll(runManager.getBeforeRunTasks(myRunConfiguration));
myModel.replaceAll(originalTasks);
myShowSettingsBeforeRunCheckBox.setSelected(settings.isEditBeforeRun());
myShowSettingsBeforeRunCheckBox.setEnabled(!(isUnknown()));
myPanel.setVisible(checkBeforeRunTasksAbility(false));
updateText();
}
private void updateText() {
StringBuilder sb = new StringBuilder();
if (myShowSettingsBeforeRunCheckBox.isSelected()) {
sb.append(ExecutionBundle.message("configuration.edit.before.run"));
}
List<BeforeRunTask> tasks = myModel.getItems();
if (!tasks.isEmpty()) {
LinkedHashMap<BeforeRunTaskProvider, Integer> counter = new LinkedHashMap<BeforeRunTaskProvider, Integer>();
for (BeforeRunTask task : tasks) {
BeforeRunTaskProvider<BeforeRunTask> provider =
BeforeRunTaskProvider.getProvider(myRunConfiguration.getProject(), task.getProviderId());
if (provider != null) {
Integer count = counter.get(provider);
if (count == null) {
count = task.getItemsCount();
} else {
count+=task.getItemsCount();
}
counter.put(provider, count);
}
}
for (Iterator<Map.Entry<BeforeRunTaskProvider, Integer>> iterator = counter.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<BeforeRunTaskProvider, Integer> entry = iterator.next();
BeforeRunTaskProvider provider = entry.getKey();
String name = provider.getName();
if (name.startsWith("Run ")) {
name = name.substring(4);
}
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(name);
if (entry.getValue() > 1) {
sb.append(" (").append(entry.getValue().intValue()).append(")");
}
}
}
if (sb.length() > 0) {
sb.insert(0, ": ");
}
sb.insert(0, ExecutionBundle.message("before.launch.panel.title"));
myListener.titleChanged(sb.toString());
}
public List<BeforeRunTask> getTasks(boolean applyCurrentState) {
if (applyCurrentState) {
originalTasks.clear();
originalTasks.addAll(myModel.getItems());
}
return Collections.unmodifiableList(originalTasks);
}
public boolean needEditBeforeRun() {
return myShowSettingsBeforeRunCheckBox.isSelected();
}
private boolean checkBeforeRunTasksAbility(boolean checkOnlyAddAction) {
if (isUnknown()) {
return false;
}
Set<Key> activeProviderKeys = getActiveProviderKeys();
final BeforeRunTaskProvider<BeforeRunTask>[] providers = Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME,
myRunConfiguration.getProject());
for (final BeforeRunTaskProvider<BeforeRunTask> provider : providers) {
if (provider.createTask(myRunConfiguration) != null) {
if (!checkOnlyAddAction) {
return true;
}
else if (!provider.isSingleton() || !activeProviderKeys.contains(provider.getId())) {
return true;
}
}
}
return false;
}
private boolean isUnknown() {
return myRunConfiguration instanceof UnknownRunConfiguration;
}
void doAddAction(AnActionButton button) {
if (isUnknown()) {
return;
}
final JBPopupFactory popupFactory = JBPopupFactory.getInstance();
final BeforeRunTaskProvider<BeforeRunTask>[] providers = Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME,
myRunConfiguration.getProject());
Set<Key> activeProviderKeys = getActiveProviderKeys();
DefaultActionGroup actionGroup = new DefaultActionGroup(null, false);
for (final BeforeRunTaskProvider<BeforeRunTask> provider : providers) {
if (provider.createTask(myRunConfiguration) == null)
continue;
if (activeProviderKeys.contains(provider.getId()) && provider.isSingleton())
continue;
AnAction providerAction = new AnAction(provider.getName(), null, provider.getIcon()) {
@Override
public void actionPerformed(AnActionEvent e) {
BeforeRunTask task = provider.createTask(myRunConfiguration);
if (task != null) {
provider.configureTask(myRunConfiguration, task);
if (!provider.canExecuteTask(myRunConfiguration, task))
return;
} else {
return;
}
task.setEnabled(true);
Set<RunConfiguration> configurationSet = new HashSet<RunConfiguration>();
getAllRunBeforeRuns(task, configurationSet);
if (configurationSet.contains(myRunConfiguration)) {
JOptionPane.showMessageDialog(BeforeRunStepsPanel.this,
ExecutionBundle.message("before.launch.panel.cyclic_dependency_warning",
myRunConfiguration.getName(),
provider.getDescription(task)),
ExecutionBundle.message("warning.common.title"),JOptionPane.WARNING_MESSAGE);
return;
}
addTask(task);
myListener.fireStepsBeforeRunChanged();
}
};
actionGroup.add(providerAction);
}
final ListPopup popup =
popupFactory.createActionGroupPopup(ExecutionBundle.message("add.new.run.configuration.acrtion.name"), actionGroup,
SimpleDataContext.getProjectContext(myRunConfiguration.getProject()), false, false, false, null,
-1, Conditions.<AnAction>alwaysTrue());
popup.show(button.getPreferredPopupPoint());
}
public void addTask(BeforeRunTask task) {
myModel.add(task);
}
private Set<Key> getActiveProviderKeys() {
Set<Key> result = new HashSet<Key>();
for (BeforeRunTask task : myModel.getItems()) {
result.add(task.getProviderId());
}
return result;
}
private void getAllRunBeforeRuns(BeforeRunTask task, Set<RunConfiguration> configurationSet) {
if (task instanceof RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask) {
RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask runTask
= (RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask)task;
RunConfiguration configuration = runTask.getSettings().getConfiguration();
List<BeforeRunTask> tasks = RunManagerImpl.getInstanceImpl(configuration.getProject()).getBeforeRunTasks(configuration);
for (BeforeRunTask beforeRunTask : tasks) {
if (beforeRunTask instanceof RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask) {
if (configurationSet.add(((RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask)beforeRunTask).getSettings().getConfiguration()))
getAllRunBeforeRuns(beforeRunTask, configurationSet);
}
}
}
}
interface StepsBeforeRunListener {
void fireStepsBeforeRunChanged();
void titleChanged(String title);
}
private class MyListCellRenderer extends JBList.StripedListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof BeforeRunTask) {
BeforeRunTask task = (BeforeRunTask)value;
BeforeRunTaskProvider<BeforeRunTask> provider = BeforeRunTaskProvider.getProvider(myRunConfiguration.getProject(), task.getProviderId());
if (provider != null) {
setIcon(provider.getTaskIcon(task));
setText(provider.getDescription(task));
}
}
return this;
}
}
}