/*
* Copyright 2003-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 jetbrains.mps.typesystem.uiActions;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.ui.ScrollPaneFactory;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.ide.ui.tree.MPSTree;
import jetbrains.mps.ide.ui.tree.MPSTreeNode;
import jetbrains.mps.ide.ui.tree.TextTreeNode;
import jetbrains.mps.ide.ui.tree.smodel.SNodeTreeNode;
import jetbrains.mps.nodeEditor.highlighter.EditorsHelper;
import jetbrains.mps.openapi.editor.Editor;
import jetbrains.mps.openapi.editor.EditorComponent;
import jetbrains.mps.openapi.navigation.EditorNavigator;
import jetbrains.mps.project.Project;
import jetbrains.mps.smodel.SNodePointer;
import jetbrains.mps.typesystem.debug.EquationLogItem;
import jetbrains.mps.util.Pair;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeId;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
public class TypecheckerStateViewComponent extends JPanel {
private static final Logger LOG = LogManager.getLogger(TypecheckerStateViewComponent.class);
private final Project myProject;
private SNode myNodeToSliceWith = null;
private List<EquationLogItem> myCurrentSlice = new ArrayList<EquationLogItem>();
public TypecheckerStateViewComponent(@NotNull Project mpsProject) {
myProject = mpsProject;
rebuild();
}
private void rebuild() {
removeAll();
setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.weightx = 1;
gridBagConstraints.weighty = 0;
gridBagConstraints.anchor = GridBagConstraints.NORTH;
gridBagConstraints.fill = GridBagConstraints.BOTH;
//upper panel
JButton debugCurrentRootButton = new JButton(new AbstractAction("Debug Current Root") {
public void actionPerformed(ActionEvent e) {
com.intellij.openapi.project.Project project = ProjectHelper.toIdeaProject(myProject);
Editor currentEditor = EditorsHelper.getSelectedEditors(FileEditorManager.getInstance(project)).get(0);
if (currentEditor != null) {
EditorComponent editorComponent = currentEditor.getCurrentEditorComponent();
if (editorComponent != null) {
final SNode currentRoot = editorComponent.getEditedNode();
debugRoot(currentRoot);
}
}
}
});
JPanel upperPanel = new JPanel();
upperPanel.setLayout(new GridBagLayout());
GridBagConstraints upperPanelConstraints = new GridBagConstraints();
upperPanelConstraints.gridx = 0;
upperPanelConstraints.gridy = 0;
upperPanelConstraints.weightx = 0;
upperPanelConstraints.weighty = 0;
upperPanelConstraints.anchor = GridBagConstraints.NORTHWEST;
upperPanel.add(debugCurrentRootButton, upperPanelConstraints);
String text = "no info collected";
upperPanelConstraints.gridx = 1;
upperPanel.add(new JLabel(text));
upperPanelConstraints.weightx = 1;
upperPanelConstraints.gridx = 2;
upperPanel.add(new JPanel(), upperPanelConstraints);
add(upperPanel, gridBagConstraints);
JPanel innerPanel = new JPanel(new GridBagLayout());
int y = 0;
GridBagConstraints innerConstraints = new GridBagConstraints();
if (myNodeToSliceWith != null) {
//initial node type
innerConstraints.gridy = y;
y++;
innerConstraints.weighty = 0;
innerConstraints.weightx = 0;
innerConstraints.fill = GridBagConstraints.NONE;
innerConstraints.anchor = GridBagConstraints.NORTHWEST;
innerConstraints.gridx = 0;
innerPanel.add(new JLabel("initial type: "), innerConstraints);
innerConstraints.gridx = 1;
innerConstraints.gridwidth = GridBagConstraints.REMAINDER;
SNodeTree initialTypeTree = new SNodeTree(null);
innerPanel.add(initialTypeTree, innerConstraints);
initialTypeTree.rebuildNow();
//innerPanel.add(nodeTypePanel, gridBagConstraints);
//slice items
innerConstraints.gridwidth = 1;
for (EquationLogItem equationLogItem : myCurrentSlice) {
innerConstraints.gridy = y;
addEquationLog(innerPanel, innerConstraints, equationLogItem);
// innerPanel.add(new EquationLogItemPanel(equationLogItem), gridBagConstraints);
y++;
}
}
innerConstraints.gridy = y;
innerConstraints.weighty = 1;
JPanel gauge = new JPanel();
gauge.setBackground(Color.WHITE);
innerPanel.add(gauge, innerConstraints);
innerPanel.setBackground(Color.WHITE);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(innerPanel);
scrollPane.setBackground(Color.WHITE);
gridBagConstraints.weighty = 1;
gridBagConstraints.gridy = 1;
add(scrollPane, gridBagConstraints);
}
public void debugRoot(final SNode currentRoot) {
}
private void openRule(String ruleModel, String ruleID) {
if (ruleModel == null || ruleID == null) return;
final SModelReference modelUID = PersistenceFacade.getInstance().createModelReference(ruleModel);
SNodeId nodeId = PersistenceFacade.getInstance().createNodeId(ruleID);
new EditorNavigator(myProject).shallFocus(true).selectIfChild().open(new SNodePointer(modelUID, nodeId));
}
public class SNodeTree extends MPSTree {
private SNode myNode;
public SNodeTree(SNode node) {
myNode = node;
}
protected MPSTreeNode rebuild() {
if (myNode == null) {
return new TextTreeNode("null");
}
return new SNodeTreeNode(myNode);
}
}
private void addEquationLog(JPanel panel, GridBagConstraints constraints, final EquationLogItem item) {
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.gridx = 0;
JLabel label = new JLabel("equation");
panel.add(label, constraints);
constraints.gridx = 1;
SNodeTree leftTree = new SNodeTree(item.getLeftRepresentator());
panel.add(leftTree, constraints);
constraints.gridx = 2;
SNodeTree rightTree = new SNodeTree(item.getRightRepresentator());
panel.add(rightTree, constraints);
constraints.gridx = 3;
constraints.weightx = 1;
JLabel reasonLabel = new JLabel(item.getReason());
reasonLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 2) {
String ruleModel = item.getRuleModel();
final String ruleID = item.getRuleId();
openRule(ruleModel, ruleID);
}
}
});
panel.add(reasonLabel, constraints);
List<Pair<String, String>> causes = item.getCauses();
constraints.gridx = 4;
constraints.weightx = 0;
if (!causes.isEmpty()) {
CausesTree causesTree = new CausesTree(causes);
panel.add(causesTree, constraints);
causesTree.rebuildNow();
} else {
add(new JLabel(""), constraints);
}
leftTree.rebuildNow();
rightTree.rebuildNow();
}
public class EquationLogItemPanel extends JPanel {
private EquationLogItem myEquationLogItem;
public EquationLogItemPanel(EquationLogItem equationLogItem) {
myEquationLogItem = equationLogItem;
setLayout(new GridBagLayout());
setBackground(Color.WHITE);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridy = 0;
constraints.weighty = 0;
constraints.weightx = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.NORTHWEST;
JLabel label = new JLabel("equation");
add(label, constraints);
constraints.gridx = 1;
SNodeTree leftTree = new SNodeTree(myEquationLogItem.getLeftRepresentator());
add(leftTree, constraints);
constraints.gridx = 2;
SNodeTree rightTree = new SNodeTree(myEquationLogItem.getRightRepresentator());
add(rightTree, constraints);
constraints.gridx = 3;
constraints.weightx = 1;
JLabel reasonLabel = new JLabel(myEquationLogItem.getReason());
reasonLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 2) {
String ruleModel = myEquationLogItem.getRuleModel();
final String ruleID = myEquationLogItem.getRuleId();
openRule(ruleModel, ruleID);
}
}
});
add(reasonLabel, constraints);
List<Pair<String, String>> causes = myEquationLogItem.getCauses();
if (!causes.isEmpty()) {
constraints.gridx = 4;
constraints.weightx = 0;
CausesTree causesTree = new CausesTree(causes);
add(causesTree, constraints);
causesTree.rebuildNow();
}
leftTree.rebuildNow();
rightTree.rebuildNow();
}
}
class CausesTree extends MPSTree {
private List<Pair<String, String>> myCauses;
public CausesTree(List<Pair<String, String>> causes) {
myCauses = new ArrayList<Pair<String, String>>(causes);
}
protected MPSTreeNode rebuild() {
TextTreeNode root = new TextTreeNode("causes");
for (final Pair<String, String> cause : myCauses) {
TextTreeNode child = new TextTreeNode(cause.o1 + " : " + cause.o2) {
public void doubleClick() {
openRule(cause.o1, cause.o2);
}
};
root.add(child);
}
return root;
}
}
}