package jetbrains.mps.vcs.diff.ui;
/*Generated by MPS */
import com.intellij.openapi.project.Project;
import jetbrains.mps.vcs.diff.StructChangeSet;
import jetbrains.mps.vcs.diff.ui.common.DiffEditor;
import java.util.List;
import jetbrains.mps.vcs.diff.ui.common.ChangeGroupLayout;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.vcs.diff.ui.common.DiffEditorSeparator;
import jetbrains.mps.vcs.diff.ui.common.DiffEditorsGroup;
import com.intellij.ui.JBSplitter;
import javax.swing.JPanel;
import java.awt.GridBagLayout;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.diff.ex.DiffStatusBar;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import jetbrains.mps.vcs.diff.ui.common.NextPreviousTraverser;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SNodeId;
import com.intellij.openapi.actionSystem.ToggleAction;
import jetbrains.mps.ide.icons.IdeIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ActionGroup;
import javax.swing.JComponent;
import jetbrains.mps.vcs.diff.ui.common.Bounds;
import com.intellij.openapi.application.ApplicationManager;
import jetbrains.mps.vcs.diff.ui.common.DiffChangeGroupLayout;
import jetbrains.mps.vcs.diff.ui.common.ChangeGroupMessages;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import jetbrains.mps.smodel.SModelOperations;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.vcs.diff.changes.ModelChange;
import jetbrains.mps.util.NameUtil;
import jetbrains.mps.vcs.diff.StructChangeSetBuilder;
public class StructDifferencePane {
private static final String PARAM_SHOW_INSPECTOR = StructDifferencePane.class.getName() + "ShowInspector";
private static final String PARAM_INSPECTOR_SPLITTER_POSITION = StructDifferencePane.class.getName() + "InspectorSplitterPosition";
private Project myProject;
private StructChangeSet myChangeSet;
private DiffEditor myOldEditor;
private DiffEditor myNewEditor;
private List<ChangeGroupLayout> myChangeGroupLayouts = ListSequence.fromList(new ArrayList<ChangeGroupLayout>());
private List<DiffEditorSeparator> myEditorSeparators = ListSequence.fromList(new ArrayList<DiffEditorSeparator>());
private DiffEditorsGroup myDiffEditorsGroup;
private JBSplitter myPanel = new JBSplitter(true, 0.7f);
private JPanel myTopPanel = new JPanel(new GridBagLayout());
private JPanel myBottomPanel = new JPanel(new GridBagLayout());
private boolean isInspectorShown = PropertiesComponent.getInstance().getBoolean(PARAM_SHOW_INSPECTOR, true);
private DiffStatusBar myStatusBar;
private DefaultActionGroup myActionGroup;
private NextPreviousTraverser myTraverser;
public StructDifferencePane(Project project, StructChangeSet changeSet, String[] titles, DiffStatusBar statusBar) {
myChangeSet = changeSet;
myProject = project;
myDiffEditorsGroup = new DiffEditorsGroup() {
@Nullable
@Override
protected SNodeId mapID(DiffEditor myEditor, SNodeId myNodeId, DiffEditor otherEditor) {
if (myEditor == otherEditor) {
return myNodeId;
}
if (myOldEditor == myEditor && myNewEditor == otherEditor) {
return myChangeSet.mapToNewId(myNodeId);
}
if (myNewEditor == myEditor && myOldEditor == otherEditor) {
return myChangeSet.mapToOldId(myNodeId);
}
return null;
}
};
myStatusBar = statusBar;
myOldEditor = addEditor(0, myChangeSet.getOldModel(), myChangeSet.getOldNodeId(), titles[0]);
myNewEditor = addEditor(1, myChangeSet.getNewModel(), myChangeSet.getNewNodeId(), titles[1]);
linkEditors(true);
linkEditors(false);
myPanel.setSplitterProportionKey(PARAM_INSPECTOR_SPLITTER_POSITION);
myPanel.setFirstComponent(myTopPanel);
if (isInspectorShown) {
myPanel.setSecondComponent(myBottomPanel);
}
myTraverser = new NextPreviousTraverser(myChangeGroupLayouts, myNewEditor.getMainEditor());
createActionGroup();
}
private void createActionGroup() {
myActionGroup = new DefaultActionGroup();
myActionGroup.addAll(myTraverser.previousAction(), myTraverser.nextAction());
myTraverser.previousAction().registerCustomShortcutSet(NextPreviousTraverser.PREV_CHANGE_SHORTCUT, myPanel);
myTraverser.nextAction().registerCustomShortcutSet(NextPreviousTraverser.NEXT_CHANGE_SHORTCUT, myPanel);
myActionGroup.addSeparator();
myActionGroup.add(new ToggleAction("Show Inspector", "Show Inspector Windows", IdeIcons.INSPECTOR_ICON) {
public boolean isSelected(AnActionEvent e) {
return isInspectorShown;
}
public void setSelected(AnActionEvent e, boolean b) {
showInspector(b);
}
});
}
public ActionGroup getActions() {
return myActionGroup;
}
public void registerShortcuts(JComponent component) {
myTraverser.previousAction().registerCustomShortcutSet(NextPreviousTraverser.PREV_CHANGE_SHORTCUT, component);
myTraverser.nextAction().registerCustomShortcutSet(NextPreviousTraverser.NEXT_CHANGE_SHORTCUT, component);
}
public void unregisterShortcuts(JComponent component) {
myTraverser.previousAction().unregisterCustomShortcutSet(component);
myTraverser.nextAction().unregisterCustomShortcutSet(component);
}
public JPanel getPanel() {
return myPanel;
}
public void navigateInitial(@Nullable final Bounds firstChange) {
highlightAllChanges();
if (firstChange != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
myTraverser.goToBounds(firstChange);
}
});
} else {
myTraverser.goToFirstChangeLater();
}
}
private void showInspector(boolean show) {
if (isInspectorShown == show) {
return;
}
isInspectorShown = show;
PropertiesComponent.getInstance().setValue(PARAM_SHOW_INSPECTOR, show + "");
myPanel.setSecondComponent((isInspectorShown ? myBottomPanel : null));
}
private void linkEditors(boolean inspector) {
// create change group builder, trapecium strip and merge buttons painter
// 'mine' parameter means mine changeset, 'inspector' - highlight inspector editor component
ChangeGroupLayout layout = new DiffChangeGroupLayout(null, myChangeSet, myOldEditor, myNewEditor, inspector);
ChangeGroupMessages.startMaintaining(layout);
ListSequence.fromList(myChangeGroupLayouts).addElement(layout);
DiffEditorSeparator separator = new DiffEditorSeparator(layout);
GridBagConstraints gbc = new GridBagConstraints(1, 0, 1, 1, 0, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 0, 5, 0), 0, 0);
((inspector ? myBottomPanel : myTopPanel)).add(separator, gbc);
ListSequence.fromList(myEditorSeparators).addElement(separator);
if (!(SModelOperations.isReadOnly(myChangeSet.getNewModel()))) {
StructDiffButtonsPainter.addTo(myOldEditor, layout, inspector);
StructDiffButtonsPainter.addTo(myNewEditor, layout, inspector);
}
}
private DiffEditor addEditor(int index, SModel model, SNodeId nodeId, String title) {
final DiffEditor result = new DiffEditor(ProjectHelper.fromIdeaProject(myProject), model.getNode(nodeId), title, index == 0);
GridBagConstraints gbc = new GridBagConstraints(index * 2, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, (index == 0 ? 5 : 0), 5, (index == 2 ? 5 : 0)), 0, 0);
myTopPanel.add(result.getTopComponent(), gbc);
myBottomPanel.add(result.getInspector().getExternalComponent(), gbc);
myDiffEditorsGroup.add(result);
return result;
}
private void highlightAllChanges() {
ListSequence.fromList(myChangeGroupLayouts).visitAll(new IVisitor<ChangeGroupLayout>() {
public void visit(ChangeGroupLayout b) {
b.invalidate();
}
});
for (ModelChange change : ListSequence.fromList(myChangeSet.getModelChanges())) {
higlightChange(myOldEditor, myChangeSet.getOldModel(), true, change);
higlightChange(myNewEditor, myChangeSet.getNewModel(), false, change);
}
ListSequence.fromList(myChangeGroupLayouts).visitAll(new IVisitor<ChangeGroupLayout>() {
public void visit(ChangeGroupLayout b) {
b.invalidate();
}
});
myOldEditor.repaintAndRebuildEditorMessages();
myNewEditor.repaintAndRebuildEditorMessages();
int count = ListSequence.fromList(myChangeSet.getModelChanges()).count();
myStatusBar.setText((count == 0 ? "no differences" : NameUtil.formatNumericalString(count, "difference")));
}
private void higlightChange(DiffEditor diffEditor, SModel model, boolean isOldEditor, ModelChange change) {
diffEditor.highlightChange(model, change, isOldEditor, null);
}
public void rehighlight() {
StructChangeSetBuilder.rebuildChangeSet(myChangeSet);
myNewEditor.unhighlightAllChanges();
myOldEditor.unhighlightAllChanges();
if (myNewEditor.getEditedNode() == null) {
myNewEditor.editNode(myChangeSet.getNewNodeId(), myChangeSet.getNewModel());
}
myNewEditor.getMainEditor().rebuildEditorContent();
myOldEditor.getMainEditor().rebuildEditorContent();
highlightAllChanges();
}
public void dispose() {
myActionGroup.removeAll();
myActionGroup = null;
myOldEditor.dispose();
myOldEditor = null;
myNewEditor.dispose();
myNewEditor = null;
ListSequence.fromList(myEditorSeparators).visitAll(new IVisitor<DiffEditorSeparator>() {
public void visit(DiffEditorSeparator s) {
s.dispose();
}
});
ListSequence.fromList(myEditorSeparators).clear();
myEditorSeparators = null;
}
}