summaryrefslogtreecommitdiff
path: root/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java')
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java182
1 files changed, 182 insertions, 0 deletions
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
new file mode 100644
index 000000000000..26c87c7de627
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2000-2014 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.dvcs;
+
+import com.intellij.dvcs.ui.DvcsBundle;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.CheckinProjectPanel;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.FilePathImpl;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.NonFocusableCheckBox;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComponent {
+
+ private static final Logger log = Logger.getInstance(DvcsCommitAdditionalComponent.class);
+
+ protected final JPanel myPanel;
+ protected final JCheckBox myAmend;
+ @Nullable private String myPreviousMessage;
+ @Nullable private String myAmendedMessage;
+ @NotNull protected final CheckinProjectPanel myCheckinPanel;
+ @Nullable private Map<VirtualFile, String> myMessagesForRoots;
+
+ public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
+ myCheckinPanel = panel;
+ myPanel = new JPanel(new GridBagLayout());
+ final Insets insets = new Insets(2, 2, 2, 2);
+ // add amend checkbox
+ GridBagConstraints c = new GridBagConstraints();
+ //todo change to MigLayout
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 2;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = insets;
+ c.weightx = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+ myAmend = new NonFocusableCheckBox(DvcsBundle.message("commit.amend"));
+ myAmend.setMnemonic('m');
+ myAmend.setToolTipText(DvcsBundle.message("commit.amend.tooltip"));
+ myPreviousMessage = myCheckinPanel.getCommitMessage();
+
+ myAmend.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (myAmend.isSelected()) {
+ if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it
+ if (myMessagesForRoots == null) {
+ loadMessagesInModalTask(project); //load all commit messages for all repositories
+ }
+ String message = constructAmendedMessage();
+ if (!StringUtil.isEmptyOrSpaces(message)) {
+ myAmendedMessage = message;
+ substituteCommitMessage(myAmendedMessage);
+ }
+ }
+ }
+ else {
+ // there was the amended message, but user has changed it => not reverting
+ if (myCheckinPanel.getCommitMessage().equals(myAmendedMessage)) {
+ myCheckinPanel.setCommitMessage(myPreviousMessage);
+ }
+ }
+ }
+ });
+ myPanel.add(myAmend, c);
+ }
+
+ private String constructAmendedMessage() {
+ Set<VirtualFile> selectedRoots = getVcsRoots(getSelectedFilePaths()); // get only selected files
+ LinkedHashSet<String> messages = ContainerUtil.newLinkedHashSet();
+ if (myMessagesForRoots != null) {
+ for (VirtualFile root : selectedRoots) {
+ String message = myMessagesForRoots.get(root);
+ if (message != null) {
+ messages.add(message);
+ }
+ }
+ }
+ return DvcsUtil.joinMessagesOrNull(messages);
+ }
+
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ public void refresh() {
+ myAmend.setSelected(false);
+ }
+
+ private void loadMessagesInModalTask(@NotNull Project project) {
+ try {
+ myMessagesForRoots =
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<Map<VirtualFile,String>, VcsException>() {
+ @Override
+ public Map<VirtualFile, String> compute() throws VcsException {
+ return getLastCommitMessages();
+ }
+ }, "Reading commit message...", false, project);
+ }
+ catch (VcsException e) {
+ Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(),
+ "Commit Message not Loaded");
+ log.info(e);
+ }
+ }
+
+ private void substituteCommitMessage(@NotNull String newMessage) {
+ myPreviousMessage = myCheckinPanel.getCommitMessage();
+ if (!myPreviousMessage.trim().equals(newMessage.trim())) {
+ myCheckinPanel.setCommitMessage(newMessage);
+ }
+ }
+
+ @Nullable
+ private Map<VirtualFile, String> getLastCommitMessages() throws VcsException {
+ Map<VirtualFile, String> messagesForRoots = new HashMap<VirtualFile, String>();
+ Collection<VirtualFile> roots = myCheckinPanel.getRoots(); //all committed vcs roots, not only selected
+ final Ref<VcsException> exception = Ref.create();
+ for (VirtualFile root : roots) {
+ String message = getLastCommitMessage(root);
+ messagesForRoots.put(root, message);
+ }
+ if (!exception.isNull()) {
+ throw exception.get();
+ }
+ return messagesForRoots;
+ }
+
+ @NotNull
+ private List<FilePath> getSelectedFilePaths() {
+ return ContainerUtil.map(myCheckinPanel.getFiles(), new Function<File, FilePath>() {
+ @Override
+ public FilePath fun(File file) {
+ return new FilePathImpl(file, file.isDirectory());
+ }
+ });
+ }
+
+ @NotNull
+ protected abstract Set<VirtualFile> getVcsRoots(@NotNull Collection<FilePath> files);
+
+ @Nullable
+ protected abstract String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException;
+}