diff options
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.java | 320 |
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; + } + } +} |