blob: 4cf5574fab9b7dbaf0b935367d0bdd37b2654237 [file] [log] [blame]
/*
* Copyright 2000-2013 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.actionSystem.CustomShortcutSet;
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.keymap.KeymapManager;
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.Comparing;
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;
// Author: dyoma
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;
}
if (hints.contains(DiffTool.HINT_DIFF_IS_APPROXIMATE)) {
diffPanel.setPatchAppliedApproximately(); // todo read only and not variants
}
final Runnable onOkRunnable = request.getOnOkRunnable();
if (onOkRunnable != null){
builder.setOkOperation(new Runnable() {
@Override
public void run() {
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(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("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;
}
if (hints.contains(DiffTool.HINT_DIFF_IS_APPROXIMATE)) {
diffPanel.setPatchAppliedApproximately();
}
frameWrapper.setTitle(request.getWindowTitle());
DiffUtil.initDiffFrame(diffPanel.getProject(), frameWrapper, diffPanel, diffPanel.getComponent());
new AnAction() {
public void actionPerformed(final AnActionEvent e) {
frameWrapper.getFrame().dispose();
}
}.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("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(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("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) {
return (DiffPanelImpl) DiffManagerImpl.createDiffPanel(request, window, parentDisposable, this);
}
static void showDiffDialog(DialogBuilder builder, Collection hints) {
builder.showModal(!hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG));
}
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)) {
DiffManagerImpl manager = (DiffManagerImpl) DiffManager.getInstance();
if (!Comparing.equal(manager.getComparisonPolicy(), ComparisonPolicy.DEFAULT)) {
ComparisonPolicy oldPolicy = manager.getComparisonPolicy();
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;
}
if (! showMessage) {
return true;
}
return !askForceOpenDiff(data);
}
return false;
}
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);
}
}