| /* |
| * Copyright 2000-2009 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.branchConfig; |
| |
| import com.intellij.openapi.actionSystem.ActionToolbarPosition; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.ui.MultiLineLabelUI; |
| import com.intellij.openapi.ui.TextFieldWithBrowseButton; |
| import com.intellij.openapi.util.Pair; |
| import com.intellij.openapi.vcs.VcsException; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.ui.*; |
| import com.intellij.ui.components.JBList; |
| import com.intellij.util.ObjectUtils; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.idea.svn.*; |
| import org.jetbrains.idea.svn.commandLine.SvnBindException; |
| import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; |
| import org.tmatesoft.svn.core.SVNURL; |
| import org.tmatesoft.svn.core.internal.util.SVNURLUtil; |
| |
| import javax.swing.*; |
| import javax.swing.event.DocumentEvent; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class BranchConfigurationDialog extends DialogWrapper { |
| private JPanel myTopPanel; |
| private TextFieldWithBrowseButton myTrunkLocationTextField; |
| private JList myLocationList; |
| private JPanel myListPanel; |
| private JLabel myErrorPrompt; |
| private final NewRootBunch mySvnBranchConfigManager; |
| private final VirtualFile myRoot; |
| |
| public BranchConfigurationDialog(@NotNull final Project project, |
| @NotNull final SvnBranchConfigurationNew configuration, |
| final @NotNull SVNURL rootUrl, |
| @NotNull final VirtualFile root, |
| @NotNull String url) { |
| super(project, true); |
| myRoot = root; |
| init(); |
| setTitle(SvnBundle.message("configure.branches.title")); |
| |
| final String trunkUrl = configuration.getTrunkUrl(); |
| if (trunkUrl == null || trunkUrl.trim().length() == 0) { |
| configuration.setTrunkUrl(url); |
| } |
| |
| mySvnBranchConfigManager = SvnBranchConfigurationManager.getInstance(project).getSvnBranchConfigManager(); |
| |
| myTrunkLocationTextField.setText(configuration.getTrunkUrl()); |
| myTrunkLocationTextField.addActionListener(new ActionListener() { |
| public void actionPerformed(final ActionEvent e) { |
| final String selectedUrl = SelectLocationDialog.selectLocation(project, myTrunkLocationTextField.getText()); |
| if (selectedUrl != null) { |
| myTrunkLocationTextField.setText(selectedUrl); |
| } |
| } |
| }); |
| |
| final TrunkUrlValidator trunkUrlValidator = new TrunkUrlValidator(rootUrl, configuration); |
| myTrunkLocationTextField.getTextField().getDocument().addDocumentListener(trunkUrlValidator); |
| trunkUrlValidator.textChanged(null); |
| |
| myErrorPrompt.setUI(new MultiLineLabelUI()); |
| myErrorPrompt.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); |
| |
| final MyListModel listModel = new MyListModel(configuration); |
| myLocationList = new JBList(listModel); |
| |
| myListPanel.add( |
| ToolbarDecorator.createDecorator(myLocationList) |
| .setAddAction(new AnActionButtonRunnable() { |
| |
| @Nullable private SVNURL usedRootUrl; |
| |
| @Override |
| public void run(AnActionButton button) { |
| Pair<String, SVNURL> result = SelectLocationDialog.selectLocation(project, ObjectUtils.notNull(usedRootUrl, rootUrl)); |
| if (result != null) { |
| String selectedUrl = result.getFirst(); |
| usedRootUrl = result.getSecond(); |
| if (selectedUrl != null) { |
| if (!configuration.getBranchUrls().contains(selectedUrl)) { |
| configuration |
| .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty)); |
| mySvnBranchConfigManager.reloadBranchesAsync(myRoot, selectedUrl, InfoReliability.setByUser); |
| listModel.fireItemAdded(); |
| myLocationList.setSelectedIndex(listModel.getSize() - 1); |
| } |
| } |
| } |
| } |
| }).setRemoveAction(new AnActionButtonRunnable() { |
| @Override |
| public void run(AnActionButton button) { |
| int selIndex = myLocationList.getSelectedIndex(); |
| Object[] selection = myLocationList.getSelectedValues(); |
| for (Object urlObj : selection) { |
| String url = (String)urlObj; |
| int index = configuration.getBranchUrls().indexOf(url); |
| configuration.removeBranch(url); |
| listModel.fireItemRemoved(index); |
| } |
| if (listModel.getSize() > 0) { |
| if (selIndex >= listModel.getSize()) |
| selIndex = listModel.getSize() - 1; |
| myLocationList.setSelectedIndex(selIndex); |
| } |
| } |
| }).disableUpDownActions().setToolbarPosition(ActionToolbarPosition.BOTTOM).createPanel(), BorderLayout.CENTER); |
| } |
| |
| private class TrunkUrlValidator extends DocumentAdapter { |
| private final SVNURL myRootUrl; |
| private final SvnBranchConfigurationNew myConfiguration; |
| |
| private TrunkUrlValidator(final SVNURL rootUrl, final SvnBranchConfigurationNew configuration) { |
| myRootUrl = rootUrl; |
| myConfiguration = configuration; |
| } |
| |
| protected void textChanged(final DocumentEvent e) { |
| SVNURL url = parseUrl(myTrunkLocationTextField.getText()); |
| |
| if (url != null) { |
| boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url); |
| boolean areNotSame = isAncestor && !url.equals(myRootUrl); |
| |
| myTrunkLocationTextField.getButton().setEnabled(isAncestor); |
| if (areNotSame) { |
| myConfiguration.setTrunkUrl(url.toDecodedString()); |
| } |
| myErrorPrompt.setText(areNotSame ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl)); |
| } |
| } |
| |
| @Nullable |
| private SVNURL parseUrl(@NotNull String url) { |
| SVNURL result = null; |
| |
| try { |
| result = SvnUtil.createUrl(url); |
| } |
| catch (SvnBindException e) { |
| myErrorPrompt.setText(e.getMessage()); |
| } |
| |
| return result; |
| } |
| } |
| |
| @Nullable |
| protected JComponent createCenterPanel() { |
| return myTopPanel; |
| } |
| |
| @Override |
| @NonNls |
| protected String getDimensionServiceKey() { |
| return "Subversion.BranchConfigurationDialog"; |
| } |
| |
| public static void configureBranches(final Project project, final VirtualFile file) { |
| configureBranches(project, file, false); |
| } |
| |
| public static void configureBranches(final Project project, final VirtualFile file, final boolean isRoot) { |
| final VirtualFile vcsRoot = (isRoot) ? file : getRoot(project, file); |
| if (vcsRoot == null) { |
| return; |
| } |
| |
| final VirtualFile directory = SvnUtil.correctRoot(project, file); |
| if (directory == null) { |
| return; |
| } |
| final RootUrlInfo wcRoot = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(directory.getPath())); |
| if (wcRoot == null) { |
| return; |
| } |
| final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl(); |
| if (rootUrl == null) { |
| Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"), |
| SvnBundle.message("configure.branches.title")); |
| return; |
| } |
| |
| SvnBranchConfigurationNew configuration; |
| try { |
| configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot); |
| } |
| catch (VcsException ex) { |
| Messages.showErrorDialog(project, "Error loading branch configuration: " + ex.getMessage(), |
| SvnBundle.message("configure.branches.title")); |
| return; |
| } |
| |
| final SvnBranchConfigurationNew clonedConfiguration = configuration.copy(); |
| BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot, wcRoot.getUrl()); |
| dlg.show(); |
| if (dlg.isOK()) { |
| SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration); |
| } |
| } |
| |
| private static VirtualFile getRoot(Project project, VirtualFile file) { |
| RootUrlInfo path = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath())); |
| return path == null ? null : path.getVirtualFile(); |
| } |
| |
| private static class MyListModel extends AbstractListModel { |
| private final SvnBranchConfigurationNew myConfiguration; |
| private List<String> myBranchUrls; |
| |
| public MyListModel(final SvnBranchConfigurationNew configuration) { |
| myConfiguration = configuration; |
| myBranchUrls = myConfiguration.getBranchUrls(); |
| } |
| |
| public int getSize() { |
| return myBranchUrls.size(); |
| } |
| |
| public Object getElementAt(final int index) { |
| return myBranchUrls.get(index); |
| } |
| |
| public void fireItemAdded() { |
| final int index = myConfiguration.getBranchUrls().size() - 1; |
| myBranchUrls = myConfiguration.getBranchUrls(); |
| super.fireIntervalAdded(this, index, index); |
| } |
| |
| public void fireItemRemoved(final int index) { |
| myBranchUrls = myConfiguration.getBranchUrls(); |
| super.fireIntervalRemoved(this, index, index); |
| } |
| } |
| } |