From 7c6249e890341ee89e36e6ec7521a073301d9a4d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 20 Mar 2011 13:25:18 +0300 Subject: [PATCH] MergeDialogCustomizer to customize titles and messages in the MultipleFileMergeDialog. 1. MergeDialogCustomizer to define description shown in the MultipleFileMergeDialog and titles above columns in the 3-way merge tool. 2. AbstractVcsHelper.showMergeDialog receive a MergeDialogCustomizer. 3. Define the customizer while unstashing during update. 4. Fix swapped local/server columns in the merge tool when unstashing during update. --- .../openapi/vcs/AbstractVcsHelper.java | 5 +- .../vcs/merge/MergeDialogCustomizer.java | 77 +++++++++++++++++++ .../vcs/impl/AbstractVcsHelperImpl.java | 7 +- .../vcs/merge/MultipleFileMergeDialog.java | 26 +++---- .../merge/GitMergeConflictResolver.java | 24 +++++- .../git4idea/update/GitStashChangesSaver.java | 19 ++++- .../zmlx/hg4idea/test/HgMockVcsHelper.java | 3 +- 7 files changed, 136 insertions(+), 25 deletions(-) create mode 100644 platform/vcs-api/src/com/intellij/openapi/vcs/merge/MergeDialogCustomizer.java diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java index 5cb11bac7de5..053cbb880d1b 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.annotate.FileAnnotation; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsHistoryProvider; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vcs.merge.MergeProvider; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; @@ -99,10 +100,10 @@ public abstract class AbstractVcsHelper { * * @param files the files to show in the merge dialog. * @param provider MergeProvider to be used for merging. - * @param description Optional description text (may be HTML) to be shown at the top of the merge dialog. + * @param mergeDialogCustomizer custom container of titles, descriptions and messages for the merge dialog. * @return changed files for which the merge was actually performed. */ - public abstract @NotNull List showMergeDialog(List files, MergeProvider provider, @Nullable String description); + public abstract @NotNull List showMergeDialog(List files, MergeProvider provider, @NotNull MergeDialogCustomizer mergeDialogCustomizer); /** * {@link #showMergeDialog(java.util.List, com.intellij.openapi.vcs.merge.MergeProvider)} without description. diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/merge/MergeDialogCustomizer.java b/platform/vcs-api/src/com/intellij/openapi/vcs/merge/MergeDialogCustomizer.java new file mode 100644 index 000000000000..cced656d72d8 --- /dev/null +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/merge/MergeDialogCustomizer.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.vcs.merge; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.VcsBundle; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * Provides custom titles and messages used in MultipleFileMergeDialog and DiffTool invoked from it. + * @author Kirill Likhodedov + */ +public class MergeDialogCustomizer { + + /** + * @param files files that have conflicted changes and are shown in the dialog. + * @return description that is shows above the list of conflicted files. Null (which is equivalent to empty) by default. + */ + public @Nullable String getMultipleFileMergeDescription(Collection files) { + return null; + } + + /** + * @param file file that is merged. + * @return title of the merge dialog invoked for a 3-way merge of a file. + */ + public @Nullable String getMergeWindowTitle(VirtualFile file) { + return VcsBundle.message("multiple.file.merge.request.title", FileUtil.toSystemDependentName(file.getPresentableUrl())); + } + + /** + * @param file file that is merged. + * @return title that is shown above the left panel in the 3-way merge dialog. "Local changes" by default. + */ + public @Nullable String getLeftPanelTitle(VirtualFile file) { + return VcsBundle.message("merge.version.title.local.changes"); + } + + /** + * @param file file that is merged. + * @return title that is shown above the center panel in the 3-way merge dialog. "Merge result" by default. + */ + public @Nullable String getCenterPanelTitle(VirtualFile file) { + return VcsBundle.message("merge.version.title.merge.result"); + } + + /** + * @param file file that is merged. + * @param lastRevisionNumber + * @return title that is shown above the right panel in the 3-way merge dialog. "Changes from server" with the revision number by default. + */ + public @Nullable String getRightPanelTitle(VirtualFile file, VcsRevisionNumber lastRevisionNumber) { + if (lastRevisionNumber != null) { + return VcsBundle.message("merge.version.title.last.version.number", lastRevisionNumber.asString()); + } else { + return VcsBundle.message("merge.version.title.last.version"); + } + } + +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java index f46c662b9b15..a61e17ad4876 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java @@ -53,6 +53,7 @@ import com.intellij.openapi.vcs.changes.committed.*; import com.intellij.openapi.vcs.changes.ui.*; import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx; import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vcs.merge.MergeProvider; import com.intellij.openapi.vcs.merge.MultipleFileMergeDialog; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; @@ -634,14 +635,14 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper { @Override @NotNull public List showMergeDialog(List files, MergeProvider provider) { - return showMergeDialog(files, provider, null); + return showMergeDialog(files, provider, new MergeDialogCustomizer()); } @Override @NotNull - public List showMergeDialog(List files, MergeProvider provider, @Nullable String description) { + public List showMergeDialog(List files, MergeProvider provider, @NotNull MergeDialogCustomizer mergeDialogCustomizer) { if (files.isEmpty()) return Collections.emptyList(); - final MultipleFileMergeDialog fileMergeDialog = new MultipleFileMergeDialog(myProject, files, provider, description); + final MultipleFileMergeDialog fileMergeDialog = new MultipleFileMergeDialog(myProject, files, provider, mergeDialogCustomizer); fileMergeDialog.show(); return fileMergeDialog.getProcessedFiles(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java index cef84e705703..6a5a28f0493b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java @@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.projectImport.ProjectOpenProcessor; import com.intellij.ui.ColoredTableCellRenderer; @@ -73,6 +74,7 @@ public class MultipleFileMergeDialog extends DialogWrapper { private final ProjectManagerEx myProjectManager; private final List myProcessedFiles = new ArrayList(); private final Set myBinaryFiles = new HashSet(); + private final MergeDialogCustomizer myMergeDialogCustomizer; private final VirtualFileRenderer myVirtualFileRenderer = new VirtualFileRenderer(); @@ -107,14 +109,16 @@ public class MultipleFileMergeDialog extends DialogWrapper { } }; - public MultipleFileMergeDialog(Project project, final List files, final MergeProvider provider, String description) { + public MultipleFileMergeDialog(Project project, final List files, final MergeProvider provider, MergeDialogCustomizer mergeDialogCustomizer) { super(project, false); myProject = project; myProjectManager = ProjectManagerEx.getInstanceEx(); myProjectManager.blockReloadingProjectOnExternalChanges(); myFiles = new ArrayList(files); myProvider = provider; + myMergeDialogCustomizer = mergeDialogCustomizer; + final String description = myMergeDialogCustomizer.getMultipleFileMergeDescription(files); if (!StringUtil.isEmptyOrSpaces(description)) { myDescriptionLabel.setText(description); } @@ -297,18 +301,14 @@ public class MultipleFileMergeDialog extends DialogWrapper { MergeRequest request = diffRequestFactory .createMergeRequest(leftText, rightText, originalText, file, myProject, ActionButtonPresentation.APPLY, ActionButtonPresentation.CANCEL_WITH_PROMPT); - String lastVersionTitle; - if (mergeData.LAST_REVISION_NUMBER != null) { - lastVersionTitle = VcsBundle.message("merge.version.title.last.version.number", mergeData.LAST_REVISION_NUMBER.asString()); - } - else { - lastVersionTitle = VcsBundle.message("merge.version.title.last.version"); - } - request.setVersionTitles( - new String[]{VcsBundle.message("merge.version.title.local.changes"), VcsBundle.message("merge.version.title.merge.result"), - lastVersionTitle}); - request - .setWindowTitle(VcsBundle.message("multiple.file.merge.request.title", FileUtil.toSystemDependentName(file.getPresentableUrl()))); + final VcsRevisionNumber lastRevisionNumber = mergeData.LAST_REVISION_NUMBER; + request.setVersionTitles(new String[] { + myMergeDialogCustomizer.getLeftPanelTitle(file), + myMergeDialogCustomizer.getCenterPanelTitle(file), + myMergeDialogCustomizer.getRightPanelTitle(file, lastRevisionNumber) + }); + request.setWindowTitle(myMergeDialogCustomizer.getMergeWindowTitle(file)); + DiffManager.getInstance().getDiffTool().show(request); if (request.getResult() == DialogWrapper.OK_EXIT_CODE) { markFileProcessed(file, MergeSession.Resolution.Merged); diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java b/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java index df26b354f90a..faf90fe1c310 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java @@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.AbstractVcsHelper; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vcs.merge.MergeProvider; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ui.UIUtil; @@ -45,7 +46,7 @@ public class GitMergeConflictResolver { private final boolean myReverseMerge; private final @NotNull String myErrorNotificationTitle; private final @NotNull String myErrorNotificationAdditionalDescription; - private final @Nullable String myMergeDialogTitle; + private final @NotNull MergeDialogCustomizer myMergeDialogCustomizer; private final AbstractVcsHelper myVcsHelper; private final GitVcs myVcs; @@ -53,11 +54,15 @@ public class GitMergeConflictResolver { * @param reverseMerge specify if reverse merge provider has to be used for merging - it is the case of rebase or stash. */ public GitMergeConflictResolver(@NotNull Project project, boolean reverseMerge, @Nullable String mergeDialogTitle, @NotNull String errorNotificationTitle, @NotNull String errorNotificationAdditionalDescription) { + this(project, reverseMerge, new SimpleMergeDialogCustomizer(mergeDialogTitle), errorNotificationTitle, errorNotificationAdditionalDescription); + } + + public GitMergeConflictResolver(@NotNull Project project, boolean reverseMerge, @NotNull MergeDialogCustomizer mergeDialogCustomizer, @NotNull String errorNotificationTitle, @NotNull String errorNotificationAdditionalDescription) { myProject = project; myReverseMerge = reverseMerge; myErrorNotificationTitle = errorNotificationTitle; myErrorNotificationAdditionalDescription = errorNotificationAdditionalDescription; - myMergeDialogTitle = mergeDialogTitle; + myMergeDialogCustomizer = mergeDialogCustomizer; myVcsHelper = AbstractVcsHelper.getInstance(project); myVcs = GitVcs.getInstance(project); } @@ -113,7 +118,7 @@ public class GitMergeConflictResolver { UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { final MergeProvider mergeProvider = myReverseMerge ? myVcs.getReverseMergeProvider() : myVcs.getMergeProvider(); - myVcsHelper.showMergeDialog(new ArrayList(finalUnmergedFiles), mergeProvider, myMergeDialogTitle); + myVcsHelper.showMergeDialog(new ArrayList(finalUnmergedFiles), mergeProvider, myMergeDialogCustomizer); } }); @@ -174,4 +179,17 @@ public class GitMergeConflictResolver { } } } + + private static class SimpleMergeDialogCustomizer extends MergeDialogCustomizer { + private final String myMergeDialogTitle; + + public SimpleMergeDialogCustomizer(String mergeDialogTitle) { + myMergeDialogTitle = mergeDialogTitle; + } + + @Override + public String getMultipleFileMergeDescription(Collection files) { + return myMergeDialogTitle; + } + } } diff --git a/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java b/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java index c45bda3cc27f..9cf6e5bf1705 100644 --- a/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java +++ b/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java @@ -28,6 +28,8 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitUtil; @@ -211,9 +213,7 @@ public class GitStashChangesSaver extends GitChangesSaver { private class UnstashConflictResolver extends GitMergeConflictResolver { public UnstashConflictResolver() { - super(GitStashChangesSaver.this.myProject, true, - "Uncommitted changes that were stashed before update have conflicts with updated files.", "Local changes were not restored", - ""); + super(GitStashChangesSaver.this.myProject, false, new UnstashMergeDialogCustomizer(), "Local changes were not restored", ""); } @Override @@ -239,5 +239,18 @@ public class GitStashChangesSaver extends GitChangesSaver { } })); } + + } + + private static class UnstashMergeDialogCustomizer extends MergeDialogCustomizer { + @Override + public String getMultipleFileMergeDescription(Collection files) { + return "Uncommitted changes that were stashed before update have conflicts with updated files."; + } + + @Override + public String getRightPanelTitle(VirtualFile file, VcsRevisionNumber lastRevisionNumber) { + return "Changes from stash"; + } } } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java index ede5ec819023..ccfa7538b3aa 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.annotate.FileAnnotation; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.history.VcsFileRevision; import com.intellij.openapi.vcs.history.VcsHistoryProvider; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vcs.merge.MergeProvider; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; @@ -111,7 +112,7 @@ public class HgMockVcsHelper extends AbstractVcsHelper { @NotNull @Override - public List showMergeDialog(List files, MergeProvider provider, @Nullable String description) { + public List showMergeDialog(List files, MergeProvider provider, @NotNull MergeDialogCustomizer mergeDialogCustomizer) { return null; }