| /* |
| * Copyright 2000-2012 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.diff.impl.incrementalMerge.ui; |
| |
| import com.intellij.icons.AllIcons; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.actionSystem.ActionManager; |
| import com.intellij.openapi.actionSystem.DataContext; |
| import com.intellij.openapi.actionSystem.IdeActions; |
| import com.intellij.openapi.actionSystem.PlatformDataKeys; |
| import com.intellij.openapi.components.ServiceManager; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.diff.*; |
| import com.intellij.openapi.diff.actions.NextDiffAction; |
| import com.intellij.openapi.diff.actions.PreviousDiffAction; |
| import com.intellij.openapi.diff.actions.ToggleAutoScrollAction; |
| import com.intellij.openapi.diff.impl.*; |
| import com.intellij.openapi.diff.impl.highlighting.FragmentSide; |
| import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter; |
| import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList; |
| import com.intellij.openapi.diff.impl.incrementalMerge.MergeList; |
| import com.intellij.openapi.diff.impl.mergeTool.MergeRequestImpl; |
| import com.intellij.openapi.diff.impl.mergeTool.MergeTool; |
| import com.intellij.openapi.diff.impl.settings.DiffMergeEditorSetting; |
| import com.intellij.openapi.diff.impl.settings.DiffMergeSettings; |
| import com.intellij.openapi.diff.impl.settings.DiffMergeSettingsAction; |
| import com.intellij.openapi.diff.impl.settings.MergeToolSettings; |
| import com.intellij.openapi.diff.impl.splitter.DiffDividerPaint; |
| import com.intellij.openapi.diff.impl.splitter.LineBlocks; |
| import com.intellij.openapi.diff.impl.util.*; |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.editor.colors.EditorColorsManager; |
| import com.intellij.openapi.editor.colors.EditorColorsScheme; |
| import com.intellij.openapi.editor.ex.EditorEx; |
| import com.intellij.openapi.editor.ex.EditorMarkupModel; |
| import com.intellij.openapi.editor.highlighter.EditorHighlighter; |
| import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; |
| import com.intellij.openapi.fileTypes.FileType; |
| import com.intellij.openapi.fileTypes.FileTypes; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.DialogBuilder; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.ui.LabeledComponent; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.ui.EditorNotificationPanel; |
| import com.intellij.util.containers.Convertor; |
| import gnu.trove.TIntHashSet; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| |
| public class MergePanel2 implements DiffViewer { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.ui.MergePanel2"); |
| private final DiffPanelOuterComponent myPanel; |
| private DiffRequest myData; |
| private MergeList myMergeList; |
| private boolean myDuringCreation = false; |
| private final SyncScrollSupport myScrollSupport = new SyncScrollSupport(); |
| private final DiffDivider[] myDividers = {new DiffDivider(FragmentSide.SIDE2), new DiffDivider(FragmentSide.SIDE1)}; |
| private boolean myScrollToFirstDiff = true; |
| |
| private final LabeledComponent[] myEditorsPanels = new LabeledComponent[EDITORS_COUNT]; |
| public static final int EDITORS_COUNT = 3; |
| private final DividersRepainter myDividersRepainter = new DividersRepainter(); |
| private StatusUpdater myStatusUpdater; |
| private final DialogBuilder myBuilder; |
| private final MyDataProvider myProvider; |
| |
| public MergePanel2(DialogBuilder builder, @NotNull Disposable parent) { |
| ArrayList<EditorPlace> editorPlaces = new ArrayList<EditorPlace>(); |
| EditorPlace.EditorListener placeListener = new EditorPlace.EditorListener() { |
| public void onEditorCreated(EditorPlace place) { |
| if (myDuringCreation) return; |
| disposeMergeList(); |
| myDuringCreation = true; |
| try { |
| tryInitView(); |
| } |
| finally { |
| myDuringCreation = false; |
| } |
| } |
| |
| public void onEditorReleased(Editor releasedEditor) { |
| LOG.assertTrue(!myDuringCreation); |
| disposeMergeList(); |
| } |
| }; |
| for (int i = 0; i < EDITORS_COUNT; i++) { |
| EditorPlace editorPlace = new EditorPlace(new DiffEditorState(i), indexToColumn(i), this); |
| Disposer.register(parent, editorPlace); |
| editorPlaces.add(editorPlace); |
| editorPlace.addListener(placeListener); |
| myEditorsPanels[i] = new LabeledComponent(); |
| myEditorsPanels[i].setLabelLocation(BorderLayout.NORTH); |
| myEditorsPanels[i].setComponent(editorPlace); |
| } |
| FontSizeSynchronizer.attachTo(editorPlaces); |
| myPanel = new DiffPanelOuterComponent(TextDiffType.MERGE_TYPES, createToolbar()); |
| myPanel.insertDiffComponent(new ThreePanels(myEditorsPanels, myDividers), new MyScrollingPanel()); |
| myProvider = new MyDataProvider(); |
| myPanel.setDataProvider(myProvider); |
| myBuilder = builder; |
| } |
| |
| /** |
| * Convert legacy-style editor (or panel) number to the {@link MergePanelColumn}. |
| * @param i 0, 1 or 2 |
| * @return Left, base or right, respectively. |
| */ |
| private static MergePanelColumn indexToColumn(int i) { |
| switch (i) { |
| case 0: return MergePanelColumn.LEFT; |
| case 1: return MergePanelColumn.BASE; |
| case 2: return MergePanelColumn.RIGHT; |
| default: throw new IllegalStateException("Incorrect value for a merge column: " + i); |
| } |
| } |
| |
| @NotNull |
| private DiffRequest.ToolbarAddons createToolbar() { |
| return new DiffRequest.ToolbarAddons() { |
| public void customize(DiffToolbar toolbar) { |
| toolbar.addAction(PreviousDiffAction.find()); |
| toolbar.addAction(NextDiffAction.find()); |
| toolbar.addSeparator(); |
| toolbar.addAction(new OpenPartialDiffAction(0, 1, AllIcons.Diff.LeftDiff)); |
| toolbar.addAction(new OpenPartialDiffAction(1, 2, AllIcons.Diff.RightDiff)); |
| toolbar.addAction(new OpenPartialDiffAction(0, 2, AllIcons.Diff.BranchDiff)); |
| toolbar.addSeparator(); |
| toolbar.addAction(new ApplyNonConflicts(myPanel)); |
| toolbar.addSeparator(); |
| toolbar.addAction(new ToggleAutoScrollAction()); |
| Project project = myData.getProject(); |
| if (project != null) { |
| toolbar.addSeparator(); |
| toolbar.addAction(new DiffMergeSettingsAction(getEditors(), ServiceManager.getService(project, MergeToolSettings.class))); |
| } |
| } |
| }; |
| } |
| |
| @NotNull |
| private Collection<Editor> getEditors() { |
| Collection<Editor> editors = new ArrayList<Editor>(3); |
| for (EditorPlace place : getEditorPlaces()) { |
| editors.add(place.getEditor()); |
| } |
| return editors; |
| } |
| |
| @NotNull |
| private Collection<EditorPlace> getEditorPlaces() { |
| Collection<EditorPlace> editorPlaces = new ArrayList<EditorPlace>(3); |
| for (LabeledComponent editorsPanel : myEditorsPanels) { |
| editorPlaces.add((EditorPlace) editorsPanel.getComponent()); |
| } |
| return editorPlaces; |
| } |
| |
| public void setScrollToFirstDiff(final boolean scrollToFirstDiff) { |
| myScrollToFirstDiff = scrollToFirstDiff; |
| } |
| |
| /** |
| * @deprecated Because it references by index. |
| */ |
| @Nullable |
| @Deprecated |
| public Editor getEditor(int index) { |
| return getEditorPlace(index).getEditor(); |
| } |
| |
| public FileType getContentType() { |
| return myData == null ? FileTypes.PLAIN_TEXT : getContentType(myData); |
| } |
| |
| /** |
| * @deprecated Because it references by index. |
| */ |
| @Deprecated |
| public String getVersionTitle(int index) { |
| return myEditorsPanels[index].getRawText(); |
| } |
| |
| /** |
| * @deprecated Because it references by index. |
| */ |
| @Deprecated |
| public EditorPlace getEditorPlace(int index) { |
| return (EditorPlace)myEditorsPanels[index].getComponent(); |
| } |
| |
| private void createMergeList() { |
| if (myData == null) return; |
| DiffContent[] contents = myData.getContents(); |
| for (int i = 0; i < EDITORS_COUNT; i++) { |
| EditorPlace editorPlace = getEditorPlace(i); |
| editorPlace.setDocument(contents[i].getDocument()); |
| setHighlighterSettings(null, editorPlace); |
| } |
| tryInitView(); |
| } |
| |
| private void tryInitView() { |
| if (!hasAllEditors()) return; |
| if (myMergeList != null) return; |
| myMergeList = MergeList.create(myData); |
| myMergeList.addListener(myDividersRepainter); |
| myStatusUpdater = StatusUpdater.install(myMergeList, myPanel); |
| Editor left = getEditor(0); |
| Editor base = getEditor(1); |
| Editor right = getEditor(2); |
| |
| setupHighlighterSettings(left, base, right); |
| |
| myMergeList.setMarkups(left, base, right); |
| EditingSides[] sides = {getFirstEditingSide(), getSecondEditingSide()}; |
| myScrollSupport.install(sides); |
| for (int i = 0; i < myDividers.length; i++) { |
| myDividers[i].listenEditors(sides[i]); |
| } |
| if (myScrollToFirstDiff) { |
| myPanel.requestScrollEditors(); |
| } |
| if (myMergeList.getErrorMessage() != null) { |
| myPanel.insertTopComponent(new EditorNotificationPanel() { |
| { |
| myLabel.setText(myMergeList.getErrorMessage()); |
| } |
| }); |
| } |
| } |
| |
| @NotNull |
| EditingSides getFirstEditingSide() { |
| return new MyEditingSides(FragmentSide.SIDE1); |
| } |
| |
| @NotNull |
| EditingSides getSecondEditingSide() { |
| return new MyEditingSides(FragmentSide.SIDE2); |
| } |
| |
| public void setAutoScrollEnabled(boolean enabled) { |
| myScrollSupport.setEnabled(enabled); |
| } |
| |
| public boolean isAutoScrollEnabled() { |
| return myScrollSupport.isEnabled(); |
| } |
| |
| private void setupHighlighterSettings(Editor left, Editor base, Editor right) { |
| Editor[] editors = new Editor[]{left, base, right}; |
| DiffContent[] contents = myData.getContents(); |
| FileType[] types = DiffUtil.chooseContentTypes(contents); |
| |
| VirtualFile fallbackFile = contents[1].getFile(); |
| FileType fallbackType = contents[1].getContentType(); |
| |
| for (int i = 0; i < 3; i++) { |
| Editor editor = editors[i]; |
| DiffContent content = contents[i]; |
| |
| EditorHighlighter highlighter = |
| createHighlighter(types[i], content.getFile(), fallbackFile, fallbackType, myData.getProject()).createHighlighter(); |
| if (highlighter != null) { |
| ((EditorEx)editor).setHighlighter(highlighter); |
| } |
| } |
| } |
| |
| private static DiffHighlighterFactory createHighlighter(FileType contentType, |
| VirtualFile file, |
| VirtualFile otherFile, |
| FileType otherType, |
| Project project) { |
| if (file == null) file = otherFile; |
| if (contentType == null) contentType = otherType; |
| |
| return new DiffHighlighterFactoryImpl(contentType, file, project); |
| } |
| |
| public void setHighlighterSettings(@Nullable EditorColorsScheme settings) { |
| for (EditorPlace place : getEditorPlaces()) { |
| setHighlighterSettings(settings, place); |
| } |
| } |
| |
| private void setHighlighterSettings(@Nullable EditorColorsScheme settings, @NotNull EditorPlace place) { |
| if (settings == null) { |
| settings = EditorColorsManager.getInstance().getGlobalScheme(); |
| } |
| Editor editor = place.getEditor(); |
| DiffEditorState editorState = place.getState(); |
| if (editor != null) { |
| ((EditorEx)editor).setHighlighter(EditorHighlighterFactory.getInstance(). |
| createEditorHighlighter(editorState.getFileType(), settings, editorState.getProject())); |
| } |
| } |
| |
| private static void initEditorSettings(@NotNull Editor editor) { |
| Project project = editor.getProject(); |
| DiffMergeSettings settings = project == null ? null : ServiceManager.getService(project, MergeToolSettings.class); |
| for (DiffMergeEditorSetting property : DiffMergeEditorSetting.values()) { |
| property.apply(editor, settings == null ? property.getDefault() : settings.getPreference(property)); |
| } |
| editor.getSettings().setLineMarkerAreaShown(true); |
| } |
| |
| private void disposeMergeList() { |
| if (myMergeList == null) return; |
| if (myStatusUpdater != null) { |
| myStatusUpdater.dispose(myMergeList); |
| myStatusUpdater = null; |
| } |
| myMergeList.removeListener(myDividersRepainter); |
| |
| myMergeList = null; |
| for (DiffDivider myDivider : myDividers) { |
| myDivider.stopListenEditors(); |
| } |
| } |
| |
| @Override |
| public boolean canShowRequest(DiffRequest request) { |
| return MergeTool.canShowRequest(request); |
| } |
| |
| public void setDiffRequest(DiffRequest data) { |
| setTitle(data.getWindowTitle()); |
| disposeMergeList(); |
| for (int i = 0; i < EDITORS_COUNT; i++) { |
| getEditorPlace(i).setDocument(null); |
| } |
| LOG.assertTrue(!myDuringCreation); |
| myDuringCreation = true; |
| myProvider.putData(data.getGenericData()); |
| try { |
| myData = data; |
| String[] titles = myData.getContentTitles(); |
| for (int i = 0; i < myEditorsPanels.length; i++) { |
| LabeledComponent editorsPanel = myEditorsPanels[i]; |
| editorsPanel.getLabel().setText(titles[i].isEmpty() ? " " : titles[i]); |
| } |
| createMergeList(); |
| data.customizeToolbar(myPanel.resetToolbar()); |
| myPanel.registerToolbarActions(); |
| if ( data instanceof MergeRequestImpl && myBuilder != null){ |
| Convertor<DialogWrapper, Boolean> preOkHook = new Convertor<DialogWrapper, Boolean>() { |
| @Override |
| public Boolean convert(DialogWrapper dialog) { |
| ChangeCounter counter = ChangeCounter.getOrCreate(myMergeList); |
| int changes = counter.getChangeCounter(); |
| int conflicts = counter.getConflictCounter(); |
| if (changes == 0 && conflicts == 0) return true; |
| return Messages.showYesNoDialog(dialog.getRootPane(), |
| DiffBundle.message("merge.dialog.apply.partially.resolved.changes.confirmation.message", changes, conflicts), |
| DiffBundle.message("apply.partially.resolved.merge.dialog.title"), |
| Messages.getQuestionIcon()) == Messages.YES; |
| } |
| }; |
| ((MergeRequestImpl)data).setActions(myBuilder, this, preOkHook); |
| } |
| } |
| finally { |
| myDuringCreation = false; |
| } |
| } |
| |
| private void setTitle(String windowTitle) { |
| JDialog parent = getDialogWrapperParent(); |
| if (parent == null) return; |
| parent.setTitle(windowTitle); |
| } |
| |
| @Nullable |
| private JDialog getDialogWrapperParent() { |
| Component panel = myPanel; |
| while (panel != null){ |
| if (panel instanceof JDialog) return (JDialog)panel; |
| panel = panel.getParent(); |
| } |
| return null; |
| } |
| |
| public JComponent getComponent() { |
| return myPanel; |
| } |
| |
| @Nullable |
| public JComponent getPreferredFocusedComponent() { |
| return getEditorPlace(1).getContentComponent(); |
| } |
| |
| public int getContentsNumber() { |
| return 3; |
| } |
| |
| @Override |
| public boolean acceptsType(DiffViewerType type) { |
| return DiffViewerType.merge.equals(type); |
| } |
| |
| private boolean hasAllEditors() { |
| for (int i = 0; i < EDITORS_COUNT; i++) { |
| if (getEditor(i) == null) return false; |
| } |
| return true; |
| } |
| |
| @Nullable |
| public MergeRequestImpl getMergeRequest() { |
| return (MergeRequestImpl)(myData instanceof MergeRequestImpl ? myData : null); |
| } |
| |
| private class MyEditingSides implements EditingSides { |
| private final FragmentSide mySide; |
| |
| private MyEditingSides(FragmentSide side) { |
| mySide = side; |
| } |
| |
| @Nullable |
| public Editor getEditor(FragmentSide side) { |
| return MergePanel2.this.getEditor(mySide.getIndex() + side.getIndex()); |
| } |
| |
| public LineBlocks getLineBlocks() { |
| return myMergeList.getChanges(mySide).getLineBlocks(); |
| } |
| } |
| |
| private class MyScrollingPanel implements DiffPanelOuterComponent.ScrollingPanel { |
| public void scrollEditors() { |
| Editor centerEditor = getEditor(1); |
| JComponent centerComponent = centerEditor.getContentComponent(); |
| if (centerComponent.isShowing()) { |
| centerComponent.requestFocus(); |
| } |
| int[] toLeft = getPrimaryBeginnings(myDividers[0].getPaint()); |
| int[] toRight = getPrimaryBeginnings(myDividers[1].getPaint()); |
| int line; |
| if (toLeft.length > 0 && toRight.length > 0) { |
| line = Math.min(toLeft[0], toRight[0]); |
| } |
| else if (toLeft.length > 0) { |
| line = toLeft[0]; |
| } |
| else if (toRight.length > 0) { |
| line = toRight[0]; |
| } |
| else { |
| return; |
| } |
| SyncScrollSupport.scrollEditor(centerEditor, line); |
| } |
| |
| private int[] getPrimaryBeginnings(DiffDividerPaint paint) { |
| FragmentSide primarySide = paint.getLeftSide(); |
| LOG.assertTrue(getEditor(1) == paint.getSides().getEditor(primarySide)); |
| return paint.getSides().getLineBlocks().getBeginnings(primarySide, true); |
| } |
| } |
| |
| class DiffEditorState { |
| private final int myIndex; |
| private Document myDocument; |
| |
| private DiffEditorState(int index) { |
| myIndex = index; |
| } |
| |
| public void setDocument(Document document) { |
| myDocument = document; |
| } |
| |
| public Document getDocument() { |
| return myDocument; |
| } |
| |
| @Nullable |
| public EditorEx createEditor() { |
| Document document = getDocument(); |
| if (document == null) return null; |
| Project project = myData.getProject(); |
| EditorEx editor = DiffUtil.createEditor(document, project, myIndex != 1); |
| |
| if (editor == null) return editor; |
| //FileType type = getFileType(); |
| //editor.setHighlighter(HighlighterFactory.createHighlighter(project, type)); |
| if (myIndex == 0) editor.setVerticalScrollbarOrientation(EditorEx.VERTICAL_SCROLLBAR_LEFT); |
| if (myIndex != 1) ((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true); |
| editor.getSettings().setFoldingOutlineShown(false); |
| editor.getFoldingModel().setFoldingEnabled(false); |
| editor.getSettings().setLineMarkerAreaShown(false); |
| editor.getSettings().setFoldingOutlineShown(false); |
| editor.getGutterComponentEx().setShowDefaultGutterPopup(false); |
| initEditorSettings(editor); |
| |
| return editor; |
| } |
| |
| public FileType getFileType() { |
| return getContentType(); |
| } |
| |
| @Nullable |
| public Project getProject() { |
| return myData == null ? null : myData.getProject(); |
| } |
| } |
| |
| private static FileType getContentType(DiffRequest diffData) { |
| FileType contentType = diffData.getContents()[1].getContentType(); |
| if (contentType == null) contentType = FileTypes.PLAIN_TEXT; |
| return contentType; |
| } |
| |
| private class MyDataProvider extends GenericDataProvider { |
| public Object getData(String dataId) { |
| if (FocusDiffSide.DATA_KEY.is(dataId)) { |
| int index = getFocusedEditorIndex(); |
| if (index < 0) return null; |
| switch (index) { |
| case 0: |
| return new BranchFocusedSide(FragmentSide.SIDE1); |
| case 1: |
| return new MergeFocusedSide(); |
| case 2: |
| return new BranchFocusedSide(FragmentSide.SIDE2); |
| } |
| } |
| else if (PlatformDataKeys.DIFF_VIEWER.is(dataId)) return MergePanel2.this; |
| return super.getData(dataId); |
| } |
| |
| private int getFocusedEditorIndex() { |
| for (int i = 0; i < EDITORS_COUNT; i++) { |
| Editor editor = getEditor(i); |
| if (editor == null) continue; |
| if (editor.getContentComponent().isFocusOwner()) return i; |
| } |
| return -1; |
| } |
| } |
| |
| private class BranchFocusedSide implements FocusDiffSide { |
| private final FragmentSide mySide; |
| |
| private BranchFocusedSide(FragmentSide side) { |
| mySide = side; |
| } |
| |
| @Nullable |
| public Editor getEditor() { |
| return MergePanel2.this.getEditor(mySide.getMergeIndex()); |
| } |
| |
| public int[] getFragmentStartingLines() { |
| return myMergeList.getChanges(mySide).getLineBlocks().getBeginnings(MergeList.BRANCH_SIDE); |
| } |
| } |
| |
| private class MergeFocusedSide implements FocusDiffSide { |
| public Editor getEditor() { |
| return MergePanel2.this.getEditor(1); |
| } |
| |
| public int[] getFragmentStartingLines() { |
| TIntHashSet beginnings = new TIntHashSet(); |
| if (myMergeList != null) { |
| for (int i = 0; i < 2; i++) { |
| FragmentSide branchSide = FragmentSide.fromIndex(i); |
| beginnings.addAll(myMergeList.getChanges(branchSide).getLineBlocks().getBeginnings(MergeList.BASE_SIDE)); |
| } |
| } |
| int[] result = beginnings.toArray(); |
| Arrays.sort(result); |
| return result; |
| } |
| } |
| |
| @Nullable |
| public static MergePanel2 fromDataContext(DataContext dataContext) { |
| DiffViewer diffComponent = PlatformDataKeys.DIFF_VIEWER.getData(dataContext); |
| return diffComponent instanceof MergePanel2 ? (MergePanel2)diffComponent : null; |
| } |
| |
| public MergeList getMergeList() { |
| return myMergeList; |
| } |
| |
| public void setColorScheme(EditorColorsScheme scheme) { |
| for (Editor editor : getEditors()) { |
| if (editor != null) { |
| ((EditorEx)editor).setColorsScheme(scheme); |
| } |
| } |
| myPanel.setColorScheme(scheme); |
| } |
| |
| private class DividersRepainter implements ChangeList.Listener { |
| |
| @Override |
| public void onChangeApplied(ChangeList source) { |
| FragmentSide side = myMergeList.getSideOf(source); |
| myDividers[side.getIndex()].repaint(); |
| } |
| |
| public void onChangeRemoved(ChangeList source) { |
| FragmentSide side = myMergeList.getSideOf(source); |
| myDividers[side.getIndex()].repaint(); |
| } |
| } |
| |
| private static class StatusUpdater implements ChangeCounter.Listener { |
| private final DiffPanelOuterComponent myPanel; |
| |
| private StatusUpdater(DiffPanelOuterComponent panel) { |
| myPanel = panel; |
| } |
| |
| public void onCountersChanged(ChangeCounter counter) { |
| int changes = counter.getChangeCounter(); |
| int conflicts = counter.getConflictCounter(); |
| String text; |
| if (changes == 0 && conflicts == 0) { |
| text = DiffBundle.message("merge.dialog.all.conflicts.resolved.message.text"); |
| } |
| else { |
| // The Bundle doesn't support such complex formats. Until that is fixed, constructing manually |
| //text = DiffBundle.message("merge.statistics.message", changes, conflicts); |
| text = makeCountersText(changes, conflicts); |
| } |
| myPanel.setStatusBarText(text); |
| } |
| |
| @NotNull |
| private static String makeCountersText(int changes, int conflicts) { |
| return makeCounterWord(changes, "change") + ". " + makeCounterWord(conflicts, "conflict"); |
| } |
| |
| @NotNull |
| private static String makeCounterWord(int number, @NotNull String word) { |
| if (number == 0) { |
| return "No " + StringUtil.pluralize(word); |
| } |
| return number + " " + StringUtil.pluralize(word, number); |
| } |
| |
| public void dispose(@NotNull MergeList mergeList) { |
| ChangeCounter.getOrCreate(mergeList).removeListener(this); |
| } |
| |
| public static StatusUpdater install(MergeList mergeList, DiffPanelOuterComponent panel) { |
| ChangeCounter counters = ChangeCounter.getOrCreate(mergeList); |
| StatusUpdater updater = new StatusUpdater(panel); |
| counters.addListener(updater); |
| updater.onCountersChanged(counters); |
| return updater; |
| } |
| } |
| |
| public static class AsComponent extends JPanel{ |
| private final MergePanel2 myMergePanel; |
| |
| public AsComponent(@NotNull Disposable parent) { |
| super(new BorderLayout()); |
| myMergePanel = new MergePanel2(null, parent); |
| add(myMergePanel.getComponent(), BorderLayout.CENTER); |
| } |
| |
| public MergePanel2 getMergePanel() { |
| return myMergePanel; |
| } |
| |
| @SuppressWarnings({"UnusedDeclaration"}) |
| public boolean isToolbarEnabled() { |
| return myMergePanel.myPanel.isToolbarEnabled(); |
| } |
| |
| public void setToolbarEnabled(boolean enabled) { |
| myMergePanel.myPanel.disableToolbar(!enabled); |
| } |
| } |
| } |