summaryrefslogtreecommitdiff
path: root/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java')
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java320
1 files changed, 320 insertions, 0 deletions
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java
new file mode 100644
index 000000000000..445ce4e9afe3
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java
@@ -0,0 +1,320 @@
+/*
+ * 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;
+ }
+ }
+}