diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index b0790e18088a..1ad5d0dd61a0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -44,9 +44,7 @@ import com.intellij.openapi.vcs.ui.CommitMessage; import com.intellij.openapi.vcs.ui.Refreshable; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.JBColor; -import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SplitterWithSecondHideable; import com.intellij.util.Alarm; import com.intellij.util.ui.AbstractLayoutManager; @@ -60,8 +58,10 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.io.File; -import java.util.*; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Set; import static com.intellij.openapi.vcs.VcsBundle.message; import static com.intellij.util.ArrayUtil.isEmpty; @@ -76,7 +76,6 @@ import static com.intellij.util.containers.ContainerUtil.mapNotNull; import static com.intellij.util.containers.ContainerUtil.newArrayList; import static com.intellij.util.containers.ContainerUtil.newHashMap; import static com.intellij.util.containers.ContainerUtil.newHashSet; -import static com.intellij.util.containers.ContainerUtil.sorted; import static java.util.Collections.*; public class CommitChangeListDialog extends DialogWrapper implements CheckinProjectPanel, TypeSafeDataProvider { @@ -92,9 +91,6 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj private static final float DETAILS_SPLITTER_PROPORTION_OPTION_DEFAULT = 0.6f; private static final boolean DETAILS_SHOW_OPTION_DEFAULT = true; - private static final Comparator VCS_COMPARATOR = Comparator.comparing(it -> it.getKeyInstanceMethod().getName(), - String::compareToIgnoreCase); - @NotNull private final Project myProject; @NotNull private final VcsConfiguration myVcsConfiguration; private final boolean myShowVcsCommit; @@ -103,15 +99,12 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj @Nullable private final CommitResultHandler myResultHandler; @NotNull private final List myHandlers = newArrayList(); - @NotNull private final Map myPerVcsOptionsPanels = newHashMap(); - @NotNull private final List myAdditionalComponents = newArrayList(); - @NotNull private final Map myCheckinChangeListSpecificComponents = newHashMap(); private final boolean myAllOfDefaultChangeListChangesIncluded; @NotNull private final Map myListComments; - @NotNull private final PseudoMap myAdditionalData; @NotNull private final List myExecutorActions; + @NotNull private final CommitOptionsPanel myCommitOptions; @NotNull private final CommitContext myCommitContext; @NotNull private final ChangeInfoCalculator myChangesInfoCalculator; @NotNull private final ChangesBrowserBase myBrowser; @@ -269,7 +262,6 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj mySingleVcs = singleVcs; myResultHandler = customResultHandler; myListComments = newHashMap(); - myAdditionalData = new PseudoMap<>(); myDiffDetails = new MyChangeProcessor(myProject); if (!myShowVcsCommit && isEmpty(executors)) { @@ -317,14 +309,12 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj setComment(initialSelection, comment); } - String actionName = getCommitActionName(); - String borderTitleName = actionName.replace("_", "").replace("&", ""); - - JPanel optionsPanel = createOptionsPanel(project, borderTitleName); + initCheckinHandlers(project); + myCommitOptions = new CommitOptionsPanel(this, myHandlers, getAffectedVcses()); restoreState(); setTitle(myShowVcsCommit ? TITLE : trimEllipsis(executors.get(0).getActionText())); - myCommitAction = myShowVcsCommit ? new CommitAction(actionName) : null; + myCommitAction = myShowVcsCommit ? new CommitAction(getCommitActionName()) : null; myExecutorActions = map(executors, CommitExecutorAction::new); if (myCommitAction != null) { myCommitAction.setOptions(myExecutorActions); @@ -341,10 +331,10 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj updateWarning(); JPanel mainPanel; - if (optionsPanel != null) { - mainPanel = new JPanel(new MyOptionsLayout(mySplitter, optionsPanel, JBUI.scale(150), JBUI.scale(400))); + if (!myCommitOptions.isEmpty()) { + mainPanel = new JPanel(new MyOptionsLayout(mySplitter, myCommitOptions, JBUI.scale(150), JBUI.scale(400))); mainPanel.add(mySplitter); - mainPanel.add(optionsPanel); + mainPanel.add(myCommitOptions); } else { mainPanel = mySplitter; @@ -414,85 +404,13 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj showDetailsIfSaved(); } - @Nullable - private JPanel createOptionsPanel(@NotNull Project project, @NotNull String borderTitleName) { - boolean hasVcsOptions = false; - Box vcsCommitOptions = Box.createVerticalBox(); - for (AbstractVcs vcs : sorted(getAffectedVcses(), VCS_COMPARATOR)) { - CheckinEnvironment checkinEnvironment = vcs.getCheckinEnvironment(); - if (checkinEnvironment != null) { - RefreshableOnComponent options = checkinEnvironment.createAdditionalOptionsPanel(this, myAdditionalData); - if (options != null) { - JPanel vcsOptions = new JPanel(new BorderLayout()); - vcsOptions.add(options.getComponent(), BorderLayout.CENTER); - vcsOptions.setBorder(IdeBorderFactory.createTitledBorder(vcs.getDisplayName(), true)); - vcsCommitOptions.add(vcsOptions); - myPerVcsOptionsPanels.put(vcs, vcsOptions); - myAdditionalComponents.add(options); - if (options instanceof CheckinChangeListSpecificComponent) { - myCheckinChangeListSpecificComponents.put(vcs.getName(), (CheckinChangeListSpecificComponent)options); - } - hasVcsOptions = true; - } - } - } - - boolean beforeVisible = false; - boolean afterVisible = false; - Box beforeBox = Box.createVerticalBox(); - Box afterBox = Box.createVerticalBox(); + private void initCheckinHandlers(@NotNull Project project) { for (BaseCheckinHandlerFactory factory : getCheckInFactories(project)) { CheckinHandler handler = factory.createHandler(this, myCommitContext); - if (CheckinHandler.DUMMY.equals(handler)) continue; - - myHandlers.add(handler); - RefreshableOnComponent beforePanel = handler.getBeforeCheckinConfigurationPanel(); - if (beforePanel != null) { - beforeBox.add(beforePanel.getComponent()); - beforeVisible = true; - myAdditionalComponents.add(beforePanel); - } - - RefreshableOnComponent afterPanel = handler.getAfterCheckinConfigurationPanel(getDisposable()); - if (afterPanel != null) { - afterBox.add(afterPanel.getComponent()); - afterVisible = true; - myAdditionalComponents.add(afterPanel); + if (!CheckinHandler.DUMMY.equals(handler)) { + myHandlers.add(handler); } } - - if (!hasVcsOptions && !beforeVisible && !afterVisible) return null; - - Box optionsBox = Box.createVerticalBox(); - if (hasVcsOptions) { - vcsCommitOptions.add(Box.createVerticalGlue()); - optionsBox.add(vcsCommitOptions); - } - - if (beforeVisible) { - beforeBox.add(Box.createVerticalGlue()); - JPanel beforePanel = new JPanel(new BorderLayout()); - beforePanel.add(beforeBox); - beforePanel.setBorder(IdeBorderFactory.createTitledBorder( - message("border.standard.checkin.options.group", borderTitleName), true)); - optionsBox.add(beforePanel); - } - - if (afterVisible) { - afterBox.add(Box.createVerticalGlue()); - JPanel afterPanel = new JPanel(new BorderLayout()); - afterPanel.add(afterBox); - afterPanel.setBorder(IdeBorderFactory.createTitledBorder( - message("border.standard.after.checkin.options.group", borderTitleName), true)); - optionsBox.add(afterPanel); - } - - optionsBox.add(Box.createVerticalGlue()); - JPanel additionalOptionsPanel = new JPanel(new BorderLayout()); - additionalOptionsPanel.add(optionsBox, BorderLayout.NORTH); - - JScrollPane optionsPane = ScrollPaneFactory.createScrollPane(additionalOptionsPanel, true); - return JBUI.Panels.simplePanel(optionsPane).withBorder(JBUI.Borders.emptyLeft(10)); } @Nullable @@ -534,9 +452,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj private void updateOnListSelection() { updateComment(); - updateVcsOptionsVisibility(); - myCheckinChangeListSpecificComponents.values() - .forEach(component -> component.onChangeListSelected((LocalChangeList)myBrowser.getSelectedChangeList())); + myCommitOptions.onChangeListSelected((LocalChangeList)myBrowser.getSelectedChangeList()); } private void updateWarning() { @@ -556,13 +472,6 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj } } - private void updateVcsOptionsVisibility() { - Collection affectedVcses = ChangesUtil.getAffectedVcses(myBrowser.getSelectedChangeList().getChanges(), myProject); - for (Map.Entry entry : myPerVcsOptionsPanels.entrySet()) { - entry.getValue().setVisible(affectedVcses.contains(entry.getKey())); - } - } - @Nullable @Override protected String getHelpId() { @@ -768,6 +677,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj @Override public void dispose() { myDisposed = true; + Disposer.dispose(myCommitOptions); Disposer.dispose(myBrowser); Disposer.dispose(myCommitMessageArea); Disposer.dispose(myOKButtonUpdateAlarm); @@ -823,7 +733,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj for (CheckinHandler handler : myHandlers) { if (!handler.acceptExecutor(executor)) continue; - CheckinHandler.ReturnResult result = handler.beforeCheckin(executor, myAdditionalData); + CheckinHandler.ReturnResult result = handler.beforeCheckin(executor, myCommitOptions.getAdditionalData()); if (result == CheckinHandler.ReturnResult.COMMIT) continue; if (result == CheckinHandler.ReturnResult.CANCEL) { restartUpdate(); @@ -903,7 +813,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj @Override public void doCancelAction() { - myCheckinChangeListSpecificComponents.values().forEach(CheckinChangeListSpecificComponent::saveState); + myCommitOptions.saveChangeListComponentsState(); saveCommentIntoChangeList(); saveComments(false); super.doCancelAction(); @@ -912,7 +822,8 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj private void doCommit(@Nullable CommitResultHandler customResultHandler) { CommitHelper helper = new CommitHelper(myProject, myBrowser.getSelectedChangeList(), getIncludedChanges(), TITLE, getCommitMessage(), myHandlers, - myAllOfDefaultChangeListChangesIncluded, false, myAdditionalData, customResultHandler, myIsAlien, mySingleVcs); + myAllOfDefaultChangeListChangesIncluded, false, myCommitOptions.getAdditionalData(), customResultHandler, myIsAlien, + mySingleVcs); helper.doCommit(); } @@ -993,25 +904,25 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj public void refresh() { ChangeListManager.getInstance(myProject).invokeAfterUpdate(() -> { myBrowser.rebuildList(); - myAdditionalComponents.forEach(RefreshableOnComponent::refresh); + myCommitOptions.refresh(); }, InvokeAfterUpdateMode.SILENT, "commit dialog", ModalityState.current()); } @Override public void saveState() { - myAdditionalComponents.forEach(RefreshableOnComponent::saveState); + myCommitOptions.saveState(); } @Override public void restoreState() { - myAdditionalComponents.forEach(RefreshableOnComponent::restoreState); + myCommitOptions.restoreState(); } // Used in plugins @SuppressWarnings("unused") @NotNull public List getAdditionalComponents() { - return unmodifiableList(myAdditionalComponents); + return myCommitOptions.getAdditionalComponents(); } private void updateButtons() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitOptionsPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitOptionsPanel.java new file mode 100644 index 000000000000..504da16093f3 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitOptionsPanel.java @@ -0,0 +1,190 @@ +/* + * Copyright 2000-2017 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.changes.ui; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.CheckinProjectPanel; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.openapi.vcs.changes.PseudoMap; +import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent; +import com.intellij.openapi.vcs.checkin.CheckinEnvironment; +import com.intellij.openapi.vcs.checkin.CheckinHandler; +import com.intellij.openapi.vcs.ui.Refreshable; +import com.intellij.openapi.vcs.ui.RefreshableOnComponent; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.components.BorderLayoutPanel; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import static com.intellij.openapi.vcs.VcsBundle.message; +import static com.intellij.util.containers.ContainerUtil.*; +import static java.util.Collections.unmodifiableList; + +public class CommitOptionsPanel extends BorderLayoutPanel implements Refreshable, Disposable { + + private static final Comparator VCS_COMPARATOR = + Comparator.comparing(it -> it.getKeyInstanceMethod().getName(), String::compareToIgnoreCase); + + @NotNull private final CheckinProjectPanel myCommitPanel; + @NotNull private final Collection myHandlers; + @NotNull private final Map myPerVcsOptionsPanels = newHashMap(); + @NotNull private final List myAdditionalComponents = newArrayList(); + @NotNull private final Map myCheckinChangeListSpecificComponents = newHashMap(); + @NotNull private final PseudoMap myAdditionalData = new PseudoMap<>(); + private final boolean myEmpty; + + public CommitOptionsPanel(@NotNull CheckinProjectPanel panel, + @NotNull Collection handlers, + @NotNull Collection vcses) { + myCommitPanel = panel; + myHandlers = handlers; + myEmpty = init(vcses); + } + + public boolean isEmpty() { + return myEmpty; + } + + @NotNull + public List getAdditionalComponents() { + return unmodifiableList(myAdditionalComponents); + } + + @NotNull + public PseudoMap getAdditionalData() { + return myAdditionalData; + } + + @Override + public void saveState() { + myAdditionalComponents.forEach(RefreshableOnComponent::saveState); + } + + @Override + public void restoreState() { + myAdditionalComponents.forEach(RefreshableOnComponent::restoreState); + } + + @Override + public void refresh() { + myAdditionalComponents.forEach(RefreshableOnComponent::refresh); + } + + public void onChangeListSelected(@NotNull LocalChangeList changeList) { + Collection affectedVcses = ChangesUtil.getAffectedVcses(changeList.getChanges(), myCommitPanel.getProject()); + for (Map.Entry entry : myPerVcsOptionsPanels.entrySet()) { + entry.getValue().setVisible(affectedVcses.contains(entry.getKey())); + } + + myCheckinChangeListSpecificComponents.values().forEach(component -> component.onChangeListSelected(changeList)); + } + + public void saveChangeListComponentsState() { + myCheckinChangeListSpecificComponents.values().forEach(CheckinChangeListSpecificComponent::saveState); + } + + @Override + public void dispose() { + } + + private boolean init(@NotNull Collection vcses) { + String borderTitleName = myCommitPanel.getCommitActionName().replace("_", "").replace("&", ""); + boolean hasVcsOptions = false; + Box vcsCommitOptions = Box.createVerticalBox(); + for (AbstractVcs vcs : sorted(vcses, VCS_COMPARATOR)) { + CheckinEnvironment checkinEnvironment = vcs.getCheckinEnvironment(); + if (checkinEnvironment != null) { + RefreshableOnComponent options = checkinEnvironment.createAdditionalOptionsPanel(myCommitPanel, myAdditionalData); + if (options != null) { + JPanel vcsOptions = new JPanel(new BorderLayout()); + vcsOptions.add(options.getComponent(), BorderLayout.CENTER); + vcsOptions.setBorder(IdeBorderFactory.createTitledBorder(vcs.getDisplayName(), true)); + vcsCommitOptions.add(vcsOptions); + myPerVcsOptionsPanels.put(vcs, vcsOptions); + myAdditionalComponents.add(options); + if (options instanceof CheckinChangeListSpecificComponent) { + myCheckinChangeListSpecificComponents.put(vcs.getName(), (CheckinChangeListSpecificComponent)options); + } + hasVcsOptions = true; + } + } + } + + boolean beforeVisible = false; + boolean afterVisible = false; + Box beforeBox = Box.createVerticalBox(); + Box afterBox = Box.createVerticalBox(); + for (CheckinHandler handler : myHandlers) { + RefreshableOnComponent beforePanel = handler.getBeforeCheckinConfigurationPanel(); + if (beforePanel != null) { + beforeBox.add(beforePanel.getComponent()); + beforeVisible = true; + myAdditionalComponents.add(beforePanel); + } + + RefreshableOnComponent afterPanel = handler.getAfterCheckinConfigurationPanel(this); + if (afterPanel != null) { + afterBox.add(afterPanel.getComponent()); + afterVisible = true; + myAdditionalComponents.add(afterPanel); + } + } + + if (!hasVcsOptions && !beforeVisible && !afterVisible) return true; + + Box optionsBox = Box.createVerticalBox(); + if (hasVcsOptions) { + vcsCommitOptions.add(Box.createVerticalGlue()); + optionsBox.add(vcsCommitOptions); + } + + if (beforeVisible) { + beforeBox.add(Box.createVerticalGlue()); + JPanel beforePanel = new JPanel(new BorderLayout()); + beforePanel.add(beforeBox); + beforePanel.setBorder(IdeBorderFactory.createTitledBorder( + message("border.standard.checkin.options.group", borderTitleName), true)); + optionsBox.add(beforePanel); + } + + if (afterVisible) { + afterBox.add(Box.createVerticalGlue()); + JPanel afterPanel = new JPanel(new BorderLayout()); + afterPanel.add(afterBox); + afterPanel.setBorder(IdeBorderFactory.createTitledBorder( + message("border.standard.after.checkin.options.group", borderTitleName), true)); + optionsBox.add(afterPanel); + } + + optionsBox.add(Box.createVerticalGlue()); + JPanel additionalOptionsPanel = new JPanel(new BorderLayout()); + additionalOptionsPanel.add(optionsBox, BorderLayout.NORTH); + + JScrollPane optionsPane = ScrollPaneFactory.createScrollPane(additionalOptionsPanel, true); + addToCenter(optionsPane).withBorder(JBUI.Borders.emptyLeft(10)); + return false; + } +}