/* * Copyright 2000-2015 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.external; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.diff.*; import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.DiffPanelImpl; import com.intellij.openapi.diff.impl.DiffUtil; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import static com.intellij.openapi.keymap.KeymapUtil.getActiveKeymapShortcuts; public class FrameDiffTool implements DiffTool { public void show(DiffRequest request) { Collection hints = request.getHints(); boolean shouldOpenDialog = shouldOpenDialog(hints); if (shouldOpenDialog) { final DialogBuilder builder = new DialogBuilder(request.getProject()); DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, builder.getWindow(), builder, true); if (diffPanel == null) { Disposer.dispose(builder); return; } final Runnable onOkRunnable = request.getOnOkRunnable(); if (onOkRunnable != null){ builder.setOkOperation(() -> { builder.getDialogWrapper().close(0); onOkRunnable.run(); }); } else { builder.removeAllActions(); } builder.setCenterPanel(diffPanel.getComponent()); builder.setPreferredFocusComponent(diffPanel.getPreferredFocusedComponent()); builder.setTitle(request.getWindowTitle()); builder.setDimensionServiceKey(request.getGroupKey()); new AnAction() { public void actionPerformed(final AnActionEvent e) { builder.getDialogWrapper().close(0); } }.registerCustomShortcutSet(getActiveKeymapShortcuts("CloseContent"), diffPanel.getComponent()); showDiffDialog(builder, hints); } else { final FrameWrapper frameWrapper = new FrameWrapper(request.getProject(), request.getGroupKey()); DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, frameWrapper.getFrame(), frameWrapper, true); if (diffPanel == null) { Disposer.dispose(frameWrapper); return; } frameWrapper.setTitle(request.getWindowTitle()); DiffUtil.initDiffFrame(diffPanel.getProject(), frameWrapper, diffPanel, diffPanel.getComponent()); new AnAction() { public void actionPerformed(final AnActionEvent e) { frameWrapper.getFrame().dispose(); } }.registerCustomShortcutSet(getActiveKeymapShortcuts("CloseContent"), diffPanel.getComponent()); frameWrapper.show(); } } /*public static void createEditableDiffFrame(final DiffRequest request) { final FrameWrapper frameWrapper = new FrameWrapper(request.getProject(), request.getGroupKey()); DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, frameWrapper.getFrame(), frameWrapper); if (diffPanel == null) return; diffPanel.setPatchAppliedApproximately(); frameWrapper.setTitle(request.getWindowTitle()); final DialogBuilder builder = new DialogBuilder(request.getProject()); builder.setCenterPanel(diffPanel.getComponent()); builder.setPreferedFocusComponent(diffPanel.getPreferredFocusedComponent()); final JPanel panel = new JPanel(new BorderLayout()); panel.add(builder.getCenterPanel(), BorderLayout.CENTER); panel.add(builder.getDialogWrapper().get); DiffUtil.initDiffFrame(frameWrapper, diffPanel); new AnAction() { public void actionPerformed(final AnActionEvent e) { frameWrapper.getFrame().dispose(); } }.registerCustomShortcutSet(getActiveKeymapShortcuts("CloseContent"), diffPanel.getComponent()); frameWrapper.show(); }*/ @Nullable private DiffPanelImpl createDiffPanelIfShouldShow(DiffRequest request, Window window, @NotNull Disposable parentDisposable, final boolean showMessage) { DiffPanelImpl diffPanel = createDiffPanelImpl(request, window, parentDisposable); if (checkNoDifferenceAndNotify(diffPanel, request, window, showMessage)) { Disposer.dispose(diffPanel); diffPanel = null; } return diffPanel; } protected DiffPanelImpl createDiffPanelImpl(@NotNull DiffRequest request, @Nullable Window window, @NotNull Disposable parentDisposable) { DiffPanelImpl panel = (DiffPanelImpl)DiffManagerImpl.createDiffPanel(request, window, parentDisposable, this); if (request.getHints().contains(DiffTool.HINT_DIFF_IS_APPROXIMATE)) { panel.setPatchAppliedApproximately(); // todo read only and not variants } return panel; } static void showDiffDialog(DialogBuilder builder, Collection hints) { builder.showModal(!hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG)); } public static boolean shouldOpenDialog(Collection hints) { if (hints.contains(DiffTool.HINT_SHOW_MODAL_DIALOG)) return true; if (hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG)) return true; if (hints.contains(DiffTool.HINT_SHOW_FRAME)) return false; return KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow() instanceof JDialog; } // TODO remove check? private boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data, final Window window, final boolean showMessage) { if (diffPanel.hasDifferences() || data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { return false; } DiffManagerImpl manager = (DiffManagerImpl)DiffManager.getInstance(); ComparisonPolicy oldPolicy = manager.getComparisonPolicy(); if (oldPolicy != ComparisonPolicy.DEFAULT) { manager.setComparisonPolicy(ComparisonPolicy.DEFAULT); Disposable parentDisposable = Disposer.newDisposable(); DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window, parentDisposable, this); manager.setComparisonPolicy(oldPolicy); boolean hasDiffs = maybeDiffPanel.hasDifferences(); Disposer.dispose(parentDisposable); if (hasDiffs) { return false; } } return !showMessage || !askForceOpenDiff(data); } private static boolean askForceOpenDiff(DiffRequest data) { byte[] bytes1; byte[] bytes2; try { bytes1 = data.getContents()[0].getBytes(); bytes2 = data.getContents()[1].getBytes(); } catch (IOException e) { MessagesEx.error(data.getProject(), e.getMessage()).showNow(); return false; } String message = Arrays.equals(bytes1, bytes2) ? DiffBundle.message("diff.contents.are.identical.message.text") : DiffBundle.message("diff.contents.have.differences.only.in.line.separators.message.text"); return Messages.showYesNoDialog(data.getProject(), message + "\n" + DiffBundle.message("show.diff.anyway.dialog.message"), DiffBundle.message("no.differences.dialog.title"), Messages.getQuestionIcon()) == Messages.YES; } public boolean canShow(DiffRequest data) { return canShowDiff(data); } public static boolean canShowDiff(DiffRequest data) { DiffContent[] contents = data.getContents(); if (contents.length != 2) return false; for (DiffContent content : contents) { if (content.isBinary()) return false; VirtualFile file = content.getFile(); if (file != null && file.isDirectory()) return false; } return true; } @Override public DiffViewer createComponent(String title, DiffRequest request, Window window, @NotNull Disposable parentDisposable) { return createDiffPanelImpl(request, window, parentDisposable); } }