blob: 77ec2db9b9290c29ae79731e2d502b262e58d7e2 [file] [log] [blame]
/*
* 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 org.jetbrains.idea.svn.config;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
import com.intellij.util.IconUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnServerFileManager;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.event.KeyEvent;
import java.util.*;
public class SvnConfigureProxiesComponent extends MasterDetailsComponent {
private final SvnServerFileManager myManager;
private final CompositeRunnable myTreeUpdaterValidator;
private final Runnable myValidator;
private JComponent myComponent;
private final TestConnectionPerformer myTestConnectionPerformer;
private ConfigureProxiesOptionsPanel myDefaultGroupPanel;
public SvnConfigureProxiesComponent(final SvnServerFileManager manager, final GroupsValidator validator, final TestConnectionPerformer testConnectionPerformer) {
myTestConnectionPerformer = testConnectionPerformer;
myValidator = validator;
myTreeUpdaterValidator = new CompositeRunnable(TREE_UPDATER, myValidator);
initTree();
myManager = manager;
fillTree();
validator.add(this);
}
public JComponent createComponent() {
if (myComponent == null) {
myComponent = super.createComponent();
}
return myComponent;
}
protected void processRemovedItems() {
// not used
}
protected boolean wasObjectStored(final Object editableObject) {
return false;
}
public String getDisplayName() {
return "HTTP proxies configuration";
}
public String getHelpTopic() {
return null;
}
private String getNewName() {
return "Unnamed";
}
private void addGroup(final ProxyGroup template) {
final ProxyGroup group;
if (template == null) {
group = new ProxyGroup(getNewName(), "", ContainerUtil.<String, String>newHashMap());
} else {
group = new ProxyGroup(getNewName(), template.getPatterns(), template.getProperties());
}
addNode(createNodeForObject(group), myRoot);
selectNodeInTree(group);
}
public List<String> getGlobalGroupRepositories(final Collection<String> all) {
// i.e. all-[all used]
final List<String> result = new LinkedList<String>(all);
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
if (! groupConfigurable.getEditableObject().isDefault()) {
result.removeAll(groupConfigurable.getRepositories());
}
}
return result;
}
public boolean validate(final ValidationListener listener) {
final Ref<String> errorMessageRef = new Ref<String>();
final Set<String> checkSet = new HashSet<String>();
final AmbiguousPatternsFinder ambiguousPatternsFinder = new AmbiguousPatternsFinder();
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
final String groupName = groupConfigurable.getEditableObject().getName();
if (checkSet.contains(groupName)) {
listener.onError(SvnBundle.message("dialog.edit.http.proxies.settings.error.same.group.names.text", groupName), myComponent, true);
return false;
}
checkSet.add(groupName);
}
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
groupConfigurable.applyImpl();
if(! groupConfigurable.validate(errorMessageRef)) {
listener.onError(errorMessageRef.get(), myComponent, false);
return false;
}
if (! groupConfigurable.getEditableObject().isDefault()) {
final String groupName = groupConfigurable.getEditableObject().getName();
final List<String> urls = groupConfigurable.getRepositories();
ambiguousPatternsFinder.acceptUrls(groupName, urls);
}
}
if(! ambiguousPatternsFinder.isValid(errorMessageRef)) {
listener.onError(errorMessageRef.get(), myComponent, false);
return false;
}
return true;
}
protected ArrayList<AnAction> createActions(final boolean fromPopup) {
ArrayList<AnAction> result = new ArrayList<AnAction>();
result.add(new AnAction("Add", "Add", IconUtil.getAddIcon()) {
{
registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
}
public void actionPerformed(AnActionEvent event) {
addGroup(null);
}
});
result.add(new MyDeleteAction(forAll(new Condition<Object>(){
public boolean value(final Object o) {
if (o instanceof MyNode) {
final MyNode node = (MyNode) o;
if (node.getConfigurable() instanceof GroupConfigurable) {
final ProxyGroup group = ((GroupConfigurable) node.getConfigurable()).getEditableObject();
return ! group.isDefault();
}
}
return false;
}
})) {
public void actionPerformed(final AnActionEvent e) {
final TreePath path = myTree.getSelectionPath();
final MyNode node = (MyNode)path.getLastPathComponent();
final MyNode parentNode = (MyNode) node.getParent();
int idx = parentNode.getIndex(node);
super.actionPerformed(e);
idx = (idx == parentNode.getChildCount()) ? idx - 1 : idx;
if (parentNode.getChildCount() > 0) {
final TreePath newSelectedPath = new TreePath(parentNode.getPath()).pathByAddingChild(parentNode.getChildAt(idx));
myTree.setSelectionPath(newSelectedPath);
}
}
});
result.add(new AnAction("Copy", "Copy", PlatformIcons.COPY_ICON) {
{
registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_MASK)), myTree);
}
public void actionPerformed(AnActionEvent event) {
// apply - for update of editable object
try {
getSelectedConfigurable().apply();
} catch (ConfigurationException e) {
// suppress & wait for OK
}
final ProxyGroup selectedGroup = (ProxyGroup) getSelectedObject();
if (selectedGroup != null) {
addGroup(selectedGroup);
}
}
public void update(AnActionEvent event) {
super.update(event);
event.getPresentation().setEnabled(getSelectedObject() != null);
}
});
return result;
}
public void apply() throws ConfigurationException {
final List<ProxyGroup> groups = new ArrayList<ProxyGroup>(myRoot.getChildCount());
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
groupConfigurable.apply();
groups.add(groupConfigurable.getEditableObject());
}
myManager.updateUserServerFile(groups);
}
public void reset() {
super.reset();
myManager.updateFromFile();
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
groupConfigurable.reset();
}
}
private MyNode createNodeForObject(final ProxyGroup group) {
final ConfigureProxiesOptionsPanel panel = new ConfigureProxiesOptionsPanel(myValidator, myTestConnectionPerformer);
final GroupConfigurable gc = new GroupConfigurable(group, myTreeUpdaterValidator, panel);
if (group.isDefault()) {
myDefaultGroupPanel = panel;
}
// first added node must be global /default group. since url-fillers for other groups forwards their updates to global group
assert myDefaultGroupPanel != null;
panel.setPatternsListener((group.isDefault()) ? PatternsListener.Empty.instance :
new RepositoryUrlFilter(panel, this, myDefaultGroupPanel));
return new MyNode(gc, group.isDefault());
}
private void fillTree() {
myRoot.removeAllChildren();
DefaultProxyGroup defaultProxyGroup = myManager.getDefaultGroup();
defaultProxyGroup = (defaultProxyGroup == null) ? new DefaultProxyGroup(Collections.<String, String>emptyMap()) : defaultProxyGroup;
final Map<String, ProxyGroup> userGroups = myManager.getGroups();
myRoot.add(createNodeForObject(defaultProxyGroup));
for (Map.Entry<String, ProxyGroup> entry : userGroups.entrySet()) {
myRoot.add(createNodeForObject(entry.getValue()));
}
TreeUtil.sort(myRoot, GroupNodesComparator.getInstance());
((DefaultTreeModel) myTree.getModel()).reload(myRoot);
}
@Override
protected Comparator<MyNode> getNodeComparator() {
return GroupNodesComparator.getInstance();
}
private static class GroupNodesComparator implements Comparator<MyNode> {
private final static GroupNodesComparator instance = new GroupNodesComparator();
private static GroupNodesComparator getInstance() {
return instance;
}
public int compare(final MyNode node1, final MyNode node2) {
if ((node1.getConfigurable() instanceof GroupConfigurable) && (node2.getConfigurable() instanceof GroupConfigurable)) {
final ProxyGroup group1 = ((GroupConfigurable) node1.getConfigurable()).getEditableObject();
final ProxyGroup group2 = ((GroupConfigurable) node2.getConfigurable()).getEditableObject();
if (group1.isDefault()) {
return -1;
}
if (group2.isDefault()) {
return 1;
}
}
return node1.getDisplayName().compareToIgnoreCase(node2.getDisplayName());
}
}
/**
* total component made invalid => for test connection to be forbidden when for ex. ambiguous settings given
*/
public void setIsValid(final boolean valid) {
for (int i = 0; i < myRoot.getChildCount(); i++) {
final MyNode node = (MyNode) myRoot.getChildAt(i);
final GroupConfigurable groupConfigurable = (GroupConfigurable) node.getConfigurable();
groupConfigurable.setIsValid(valid);
}
}
}