diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs-impl/src/com/intellij/dvcs/AmendComponent.java similarity index 83% rename from platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java rename to platform/dvcs-impl/src/com/intellij/dvcs/AmendComponent.java index edda3b2a767f..52bd20c7c59b 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/AmendComponent.java @@ -27,12 +27,10 @@ import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsConfiguration; 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 com.intellij.util.ui.JBUI; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,33 +43,29 @@ import java.io.File; import java.util.*; import java.util.List; -public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComponent { +/** + * Provides a checkbox to amend current commit to the previous commit. + * Selecting a checkbox loads the previous commit message from the provider, and substitutes current message in the editor, + * unless it was already modified by user. + */ +public abstract class AmendComponent { - private static final Logger log = Logger.getInstance(DvcsCommitAdditionalComponent.class); + private static final Logger LOG = Logger.getInstance(AmendComponent.class); - protected final JPanel myPanel; - protected final JCheckBox myAmend; + @NotNull protected final JCheckBox myAmend; @NotNull private final String myPreviousMessage; @Nullable private String myAmendedMessage; @NotNull protected final CheckinProjectPanel myCheckinPanel; @Nullable private Map myMessagesForRoots; - public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) { - myCheckinPanel = panel; - myPanel = new JPanel(new GridBagLayout()); - final Insets insets = JBUI.insets(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; + public AmendComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) { + this(project, panel, DvcsBundle.message("commit.amend")); + } - myAmend = new NonFocusableCheckBox(DvcsBundle.message("commit.amend")); + public AmendComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel, @NotNull String title) { + myCheckinPanel = panel; + + myAmend = new NonFocusableCheckBox(title); myAmend.setMnemonic('m'); myAmend.setToolTipText(DvcsBundle.message("commit.amend.tooltip")); myPreviousMessage = myCheckinPanel.getCommitMessage(); @@ -99,7 +93,6 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp } } }); - myPanel.add(myAmend, c); } private String constructAmendedMessage() { @@ -116,14 +109,20 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp return DvcsUtil.joinMessagesOrNull(messages); } - public JComponent getComponent() { - return myPanel; - } - public void refresh() { myAmend.setSelected(false); } + @NotNull + public Component getComponent() { + return myAmend; + } + + @NotNull + public JCheckBox getCheckBox() { + return myAmend; + } + private void loadMessagesInModalTask(@NotNull Project project) { try { myMessagesForRoots = @@ -135,9 +134,9 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp }, "Reading commit message...", false, project); } catch (VcsException e) { - Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(), + Messages.showErrorDialog(project, "Couldn't load commit message of the commit to amend.\n" + e.getMessage(), "Commit Message not Loaded"); - log.info(e); + LOG.info(e); } } diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index d117329f2d6d..24013f4e7368 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -16,7 +16,7 @@ package git4idea.checkin; import com.intellij.CommonBundle; -import com.intellij.dvcs.DvcsCommitAdditionalComponent; +import com.intellij.dvcs.AmendComponent; import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.push.ui.VcsPushDialog; import com.intellij.openapi.application.ModalityState; @@ -39,6 +39,7 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.EditorTextField; import com.intellij.ui.GuiUtils; +import com.intellij.ui.components.JBLabel; import com.intellij.util.Function; import com.intellij.util.FunctionUtil; import com.intellij.util.NullableFunction; @@ -47,6 +48,7 @@ import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; import com.intellij.util.textCompletion.TextCompletionProvider; import com.intellij.util.textCompletion.TextFieldWithCompletion; import com.intellij.util.textCompletion.ValuesCompletionProvider.ValuesCompletionProviderDumbAware; +import com.intellij.util.ui.GridBag; import com.intellij.util.ui.JBUI; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsUser; @@ -81,6 +83,7 @@ import java.util.List; import static com.intellij.dvcs.DvcsUtil.getShortRepositoryName; import static com.intellij.openapi.vcs.changes.ChangesUtil.getAfterPath; import static com.intellij.openapi.vcs.changes.ChangesUtil.getBeforePath; +import static com.intellij.util.ObjectUtils.assertNotNull; import static com.intellij.util.containers.ContainerUtil.*; import static git4idea.GitUtil.getLogString; @@ -688,42 +691,39 @@ public class GitCheckinEnvironment implements CheckinEnvironment { myNextCommitAuthorDate = null; } - private class GitCheckinOptions extends DvcsCommitAdditionalComponent implements CheckinChangeListSpecificComponent { - private final GitVcs myVcs; + private class GitCheckinOptions implements CheckinChangeListSpecificComponent, RefreshableOnComponent { + @NotNull private final GitVcs myVcs; + @NotNull private JPanel myPanel; @NotNull private final EditorTextField myAuthorField; @Nullable private Date myAuthorDate; + @NotNull private AmendComponent myAmendComponent; - GitCheckinOptions(@NotNull final Project project, @NotNull CheckinProjectPanel panel) { - super(project, panel); - myVcs = GitVcs.getInstance(project); - final Insets insets = JBUI.insets(2); - // add authors drop down - GridBagConstraints c = new GridBagConstraints(); - c.gridx = 0; - c.gridy = 0; - c.anchor = GridBagConstraints.WEST; - c.insets = insets; - final JLabel authorLabel = new JLabel(GitBundle.message("commit.author")); - myPanel.add(authorLabel, c); + GitCheckinOptions(@NotNull Project project, @NotNull CheckinProjectPanel panel) { + myVcs = assertNotNull(GitVcs.getInstance(project)); - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.insets = insets; - c.gridx = 1; - c.gridy = 0; - c.weightx = 1; - c.fill = GridBagConstraints.HORIZONTAL; + myAuthorField = createTextField(project, getAuthors(project)); + myAuthorField.setToolTipText(GitBundle.getString("commit.author.tooltip")); + JLabel authorLabel = new JBLabel(GitBundle.message("commit.author")); + authorLabel.setLabelFor(myAuthorField); + myAmendComponent = new MyAmendComponent(project, panel); + + GridBag gb = new GridBag(). + setDefaultAnchor(GridBagConstraints.WEST). + setDefaultInsets(JBUI.insets(2)); + myPanel = new JPanel(new GridBagLayout()); + myPanel.add(authorLabel, gb.nextLine().next()); + myPanel.add(myAuthorField, gb.next().fillCellHorizontally().weightx(1)); + myPanel.add(myAmendComponent.getComponent(), gb.nextLine().next().coverLine()); + } + + @NotNull + private List getAuthors(@NotNull Project project) { Set authors = new HashSet<>(getUsersList(project)); addAll(authors, mySettings.getCommitAuthors()); List list = new ArrayList<>(authors); Collections.sort(list); - - myAuthorField = createTextField(project, list); - - authorLabel.setLabelFor(myAuthorField); - myAuthorField.setToolTipText(GitBundle.getString("commit.author.tooltip")); - myPanel.add(myAuthorField, c); + return list; } @NotNull @@ -733,28 +733,34 @@ public class GitCheckinEnvironment implements CheckinEnvironment { return new TextFieldWithCompletion(project, completionProvider, "", true, true, true); } - @Override - @NotNull - protected Set getVcsRoots(@NotNull Collection filePaths) { - return GitUtil.gitRoots(filePaths); - } + private class MyAmendComponent extends AmendComponent { + public MyAmendComponent(Project project, CheckinProjectPanel panel) { + super(project, panel); + } - @Nullable - @Override - protected String getLastCommitMessage(@NotNull VirtualFile root) throws VcsException { - GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LOG); - h.addParameters("--max-count=1"); - String formatPattern; - if (GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion())) { - formatPattern = "%B"; + @NotNull + @Override + protected Set getVcsRoots(@NotNull Collection files) { + return GitUtil.gitRoots(files); } - else { - // only message: subject + body; "%-b" means that preceding line-feeds will be deleted if the body is empty - // %s strips newlines from subject; there is no way to work around it before 1.7.2 with %B (unless parsing some fixed format) - formatPattern = "%s%n%n%-b"; + + @Nullable + @Override + protected String getLastCommitMessage(@NotNull VirtualFile root) throws VcsException { + GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LOG); + h.addParameters("--max-count=1"); + String formatPattern; + if (GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion())) { + formatPattern = "%B"; + } + else { + // only message: subject + body; "%-b" means that preceding line-feeds will be deleted if the body is empty + // %s strips newlines from subject; there is no way to work around it before 1.7.2 with %B (unless parsing some fixed format) + formatPattern = "%s%n%n%-b"; + } + h.addParameters("--pretty=format:" + formatPattern); + return h.run(); } - h.addParameters("--pretty=format:" + formatPattern); - return h.run(); } @NotNull @@ -770,7 +776,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment { @Override public void refresh() { - super.refresh(); + myAmendComponent.refresh(); myAuthorField.setText(null); myAuthorDate = null; reset(); @@ -786,7 +792,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment { myNextCommitAuthor = GitCommitAuthorCorrector.correct(author); mySettings.saveCommitAuthor(myNextCommitAuthor); } - myNextCommitAmend = myAmend.isSelected(); + myNextCommitAmend = myAmendComponent.isAmend(); myNextCommitAuthorDate = myAuthorDate; } @@ -809,6 +815,11 @@ public class GitCheckinEnvironment implements CheckinEnvironment { myAuthorDate = null; } } + + @Override + public JComponent getComponent() { + return myPanel; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index f11415171c92..61807541a698 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -12,7 +12,7 @@ // limitations under the License. package org.zmlx.hg4idea.provider.commit; -import com.intellij.dvcs.DvcsCommitAdditionalComponent; +import com.intellij.dvcs.AmendComponent; import com.intellij.dvcs.push.ui.VcsPushDialog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -20,7 +20,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; @@ -32,6 +31,7 @@ import com.intellij.util.FunctionUtil; import com.intellij.util.NullableFunction; import com.intellij.util.PairConsumer; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.GridBag; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import com.intellij.vcsUtil.VcsUtil; @@ -310,50 +310,47 @@ public class HgCheckinEnvironment implements CheckinEnvironment { /** * Commit options for hg */ - private class HgCommitAdditionalComponent extends DvcsCommitAdditionalComponent { + private class HgCommitAdditionalComponent implements RefreshableOnComponent { + @NotNull private final JPanel myPanel; + @NotNull private final AmendComponent myAmend; @NotNull private final JCheckBox myCommitSubrepos; public HgCommitAdditionalComponent(@NotNull Project project, @NotNull CheckinProjectPanel panel) { - super(project, panel); HgVcs myVcs = HgVcs.getInstance(myProject); - myAmend.setEnabled(myVcs != null && myVcs.getVersion().isAmendSupported()); - myAmend.setText(myAmend.getText() + " (QRefresh)"); - final Insets insets = JBUI.insets(2); - // add commit subrepos checkbox - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.insets = insets; - c.gridx = 1; - c.gridy = 2; - c.weightx = 1; - c.fill = GridBagConstraints.HORIZONTAL; + + myAmend = new MyAmendComponent(project, panel, "Amend Commit (QRefresh)"); + myAmend.getComponent().setEnabled(myVcs != null && myVcs.getVersion().isAmendSupported()); + myCommitSubrepos = new JCheckBox("Commit subrepositories", false); myCommitSubrepos.setToolTipText(XmlStringUtil.wrapInHtml( "Commit all subrepos for selected repositories.
" + " hg ci files -S subrepos")); myCommitSubrepos.setMnemonic('s'); - myPanel.add(myCommitSubrepos, c); - Collection repos = - HgActionUtil.collectRepositoriesFromFiles(HgUtil.getRepositoryManager(myProject), myCheckinPanel.getRoots()); - myCommitSubrepos.setVisible(ContainerUtil.exists(repos, new Condition() { - @Override - public boolean value(HgRepository repository) { - return repository.hasSubrepos(); - } - })); - myCommitSubrepos.addActionListener(new MySelectionListener(myAmend)); - myAmend.addActionListener(new MySelectionListener(myCommitSubrepos)); + Collection repos = HgActionUtil.collectRepositoriesFromFiles(HgUtil.getRepositoryManager(myProject), panel.getRoots()); + myCommitSubrepos.setVisible(ContainerUtil.exists(repos, HgRepository::hasSubrepos)); + + myCommitSubrepos.addActionListener(new MySelectionListener(myAmend.getCheckBox())); + myAmend.getCheckBox().addActionListener(new MySelectionListener(myCommitSubrepos)); + + GridBag gb = new GridBag(). + setDefaultInsets(JBUI.insets(2)). + setDefaultAnchor(GridBagConstraints.WEST). + setDefaultWeightX(1). + setDefaultFill(GridBagConstraints.HORIZONTAL); + myPanel = new JPanel(new GridBagLayout()); + myPanel.add(myAmend.getComponent(), gb.nextLine().next()); + myPanel.add(myCommitSubrepos, gb.nextLine().next()); } @Override public void refresh() { - super.refresh(); + myAmend.refresh(); restoreState(); } @Override public void saveState() { - myNextCommitAmend = myAmend.isSelected(); + myNextCommitAmend = myAmend.isAmend(); myShouldCommitSubrepos = myCommitSubrepos.isSelected(); } @@ -363,23 +360,34 @@ public class HgCheckinEnvironment implements CheckinEnvironment { myShouldCommitSubrepos = false; } - @NotNull @Override - protected Set getVcsRoots(@NotNull Collection filePaths) { - return HgUtil.hgRoots(myProject, filePaths); + public JComponent getComponent() { + return myPanel; } - @Nullable - @Override - protected String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException { - HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject); - List args = new ArrayList<>(); - args.add("-r"); - args.add("."); - args.add("--template"); - args.add("{desc}"); - HgCommandResult result = commandExecutor.executeInCurrentThread(repo, "log", args); - return result == null ? "" : result.getRawOutput(); + private class MyAmendComponent extends AmendComponent { + public MyAmendComponent(@NotNull Project project, @NotNull CheckinProjectPanel panel, @NotNull String title) { + super(project, panel, title); + } + + @NotNull + @Override + protected Set getVcsRoots(@NotNull Collection filePaths) { + return HgUtil.hgRoots(myProject, filePaths); + } + + @Nullable + @Override + protected String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException { + HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject); + List args = new ArrayList<>(); + args.add("-r"); + args.add("."); + args.add("--template"); + args.add("{desc}"); + HgCommandResult result = commandExecutor.executeInCurrentThread(repo, "log", args); + return result == null ? "" : result.getRawOutput(); + } } private class MySelectionListener implements ActionListener {