blob: 445ce4e9afe3a58783004c043e6903ac6e369a0b [file] [log] [blame]
/*
* 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.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.components.JBList;
import com.intellij.util.continuation.ModalityIgnorantBackgroundableTask;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnFileUrlMapping;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class SelectBranchPopup {
private final static String CONFIGURE_MESSAGE = SvnBundle.message("configure.branches.item");
private SelectBranchPopup() {
}
public interface BranchSelectedCallback {
void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision);
}
public static void show(Project project, VirtualFile file, BranchSelectedCallback callback, final String title) {
show(project, file, callback, title, null);
}
public static void show(Project project, VirtualFile file, BranchSelectedCallback callback, final String title, final Component component) {
final SvnFileUrlMapping urlMapping = SvnVcs.getInstance(project).getSvnFileUrlMapping();
final SVNURL svnurl = urlMapping.getUrlForFile(new File(file.getPath()));
if (svnurl == null) {
return;
}
final RootUrlInfo rootUrlInfo = urlMapping.getWcRootForUrl(svnurl.toString());
if (rootUrlInfo == null) {
return;
}
// not vcs root but wc root is ok
showForBranchRoot(project, rootUrlInfo.getVirtualFile(), callback, title, component);
}
public static void showForBranchRoot(Project project, VirtualFile vcsRoot, BranchSelectedCallback callback, final String title) {
showForBranchRoot(project, vcsRoot, callback, title, null);
}
public static void showForBranchRoot(Project project, VirtualFile vcsRoot, BranchSelectedCallback callback, final String title,
final Component component) {
final SvnBranchConfigurationNew configuration;
try {
configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot);
}
catch (VcsException e1) {
Messages.showErrorDialog(project, SvnBundle.message("getting.branch.configuration.error", e1.getMessage()), title);
return;
}
final List<String> items = new ArrayList<String>();
if (! StringUtil.isEmptyOrSpaces(configuration.getTrunkUrl())) {
items.add(getTrunkString(configuration));
}
for (String url : configuration.getBranchUrls()) {
items.add(url);
}
items.add(CONFIGURE_MESSAGE);
BranchBasesPopupStep step = new BranchBasesPopupStep(project, vcsRoot, configuration, callback, items, title, component);
final ListPopup listPopup = JBPopupFactory.getInstance().createListPopup(step);
step.showPopupAt(listPopup);
}
private static String getTrunkString(final SvnBranchConfigurationNew configuration) {
return configuration.getTrunkUrl() + " (trunk)";
}
private static class BranchBasesPopupStep extends BaseListPopupStep<String> {
protected final Project myProject;
private final VirtualFile myVcsRoot;
private final SvnBranchConfigurationNew myConfiguration;
private final boolean myTopLevel;
private BranchSelectedCallback myCallback;
private final Component myComponent;
private static final String REFRESH_MESSAGE = SvnBundle.message("refresh.branches.item");
private String myTrunkString;
protected BranchBasesPopupStep(final Project project,
final VirtualFile vcsRoot,
final SvnBranchConfigurationNew configuration,
boolean topLevel,
final BranchSelectedCallback callback,
Component component) {
myProject = project;
myVcsRoot = vcsRoot;
myConfiguration = configuration;
myTrunkString = getTrunkString(configuration);
myTopLevel = topLevel;
myCallback = callback;
myComponent = component;
}
public BranchBasesPopupStep(final Project project, final VirtualFile vcsRoot,
final SvnBranchConfigurationNew configuration,
final BranchSelectedCallback callback,
final List<String> items,
final String title,
Component component) {
this(project, vcsRoot, configuration, true, callback, component);
init(title, items, null);
}
@Override
public ListSeparator getSeparatorAbove(final String value) {
return (CONFIGURE_MESSAGE.equals(value)) ||
(REFRESH_MESSAGE.equals(value)) ? new ListSeparator("") : null;
}
@NotNull
@Override
public String getTextFor(final String value) {
int pos = value.lastIndexOf('/');
if (pos < 0) {
return value;
}
if (myTopLevel && ((myConfiguration.getTrunkUrl() == null) || (! value.startsWith(myConfiguration.getTrunkUrl())))) {
return value.substring(pos+1) + "...";
}
return value.substring(pos+1);
}
@Override
public boolean hasSubstep(final String selectedValue) {
return false;
}
@Override
public PopupStep onChosen(final String selectedValue, final boolean finalChoice) {
if (CONFIGURE_MESSAGE.equals(selectedValue)) {
return doFinalStep(new Runnable() {
public void run() {
BranchConfigurationDialog.configureBranches(myProject, myVcsRoot, true);
}
});
}
else if (myTrunkString.equals(selectedValue)) {
return doFinalStep(new Runnable() {
public void run() {
myCallback.branchSelected(myProject, myConfiguration, myConfiguration.getTrunkUrl(), -1);
}
});
}
else if (!myTopLevel || selectedValue.equals(myConfiguration.getTrunkUrl())) {
return doFinalStep(new Runnable() {
public void run() {
myCallback.branchSelected(myProject, myConfiguration, selectedValue, -1);
}
});
}
else {
showBranchPopup(selectedValue);
}
return FINAL_CHOICE;
}
@Nullable
private void loadBranches(final String selectedBranchesHolder, final Runnable runnable) {
final ProgressManager pm = ProgressManager.getInstance();
pm.run(new ModalityIgnorantBackgroundableTask(myProject, SvnBundle.message("compare.with.branch.progress.loading.branches")) {
@Override
protected void doInAwtIfFail(Exception e) {
runnable.run();
}
@Override
protected void doInAwtIfCancel() {
runnable.run();
}
@Override
protected void doInAwtIfSuccess() {
runnable.run();
}
@Override
protected void runImpl(@NotNull ProgressIndicator indicator) {
final NewRootBunch manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager();
manager.reloadBranches(myVcsRoot, selectedBranchesHolder, InfoReliability.setByUser, false);
}
});
}
private void showBranchPopup(final String selectedValue) {
List<SvnBranchItem> branches = myConfiguration.getBranches(selectedValue);
if (branches == null) {
return;
}
final Object[] items = new Object[branches.size() + 1];
System.arraycopy(branches.toArray(), 0, items, 0, branches.size());
items[items.length - 1] = REFRESH_MESSAGE;
final JList branchList = new JBList(items);
branchList.setCellRenderer(new BranchRenderer());
final JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(branchList)
.setTitle(SVNPathUtil.tail(selectedValue))
.setResizable(true)
//.setDimensionServiceKey("Svn.CompareWithBranchPopup")
.setItemChoosenCallback(new Runnable() {
public void run() {
if (REFRESH_MESSAGE.equals(branchList.getSelectedValue())) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
loadBranches(selectedValue, new Runnable() {
@Override
public void run() {
showBranchPopup(selectedValue);
}
});
}
});
return;
}
SvnBranchItem item = (SvnBranchItem)branchList.getSelectedValue();
if (item != null) {
myCallback.branchSelected(myProject, myConfiguration, item.getUrl(), item.getRevision());
}
}
})
.createPopup();
showPopupAt(popup);
}
public void showPopupAt(final JBPopup listPopup) {
if (myComponent == null) {
listPopup.showCenteredInCurrentWindow(myProject);
} else {
listPopup.showInCenterOf(myComponent);
}
}
}
private static class BranchRenderer extends JPanel implements ListCellRenderer {
private final JLabel myUrlLabel = new JLabel();
private final JLabel myDateLabel = new JLabel();
public BranchRenderer() {
super(new BorderLayout());
add(myUrlLabel, BorderLayout.WEST);
add(myDateLabel, BorderLayout.EAST);
myUrlLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
myDateLabel.setHorizontalAlignment(JLabel.RIGHT);
myDateLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
myDateLabel.setForeground(UIUtil.getInactiveTextColor());
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (isSelected || cellHasFocus) {
setBackground(UIUtil.getListSelectionBackground());
final Color selectedForegroundColor = UIUtil.getListSelectionForeground();
myUrlLabel.setForeground(selectedForegroundColor);
myDateLabel.setForeground(selectedForegroundColor);
setForeground(selectedForegroundColor);
}
else {
setBackground(UIUtil.getListBackground());
final Color foregroundColor = UIUtil.getListForeground();
myUrlLabel.setForeground(foregroundColor);
myDateLabel.setForeground(UIUtil.getInactiveTextColor());
setForeground(foregroundColor);
}
if (value instanceof String) {
myUrlLabel.setText((String) value);
myDateLabel.setText("");
} else {
SvnBranchItem item = (SvnBranchItem) value;
myUrlLabel.setText(SVNPathUtil.tail(item.getUrl()));
final long creationMillis = item.getCreationDateMillis();
myDateLabel.setText((creationMillis > 0) ? DateFormatUtil.formatDate(creationMillis) : "");
}
return this;
}
}
}