package jetbrains.mps.vcs.diff.ui.common; /*Generated by MPS */ import com.intellij.ui.treeStructure.SimpleTree; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.util.Ref; import org.jetbrains.mps.openapi.model.SNodeId; import java.util.List; import jetbrains.mps.workbench.action.BaseAction; import com.intellij.util.ui.tree.TreeUtil; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.IVisitor; import com.intellij.ui.ColoredTreeCellRenderer; import javax.swing.JTree; import jetbrains.mps.workbench.action.ActionUtils; import com.intellij.openapi.actionSystem.ActionPlaces; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionEvent; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.internal.collections.runtime.ISelector; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.Collections; import org.jetbrains.annotations.Nullable; import javax.swing.tree.TreePath; import jetbrains.mps.smodel.ModelAccess; import javax.swing.tree.DefaultTreeModel; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NonNls; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations; import jetbrains.mps.ide.icons.IdeIcons; import javax.swing.Icon; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.ide.icons.IconManager; import javax.swing.tree.DefaultMutableTreeNode; import com.intellij.ui.SimpleTextAttributes; import java.awt.Color; public abstract class DiffModelTree extends SimpleTree implements DataProvider { public static DataKey<Ref<SNodeId>> NODE_ID_DATAKEY = DataKey.create("MPS_SNodeId"); private List<DiffModelTree.RootTreeNode> myRootNodes; private Iterable<BaseAction> myActions; public DiffModelTree() { rebuildNow(); TreeUtil.expandAll(this); myActions = getRootActions(); Sequence.fromIterable(myActions).visitAll(new IVisitor<BaseAction>() { public void visit(BaseAction a) { a.registerCustomShortcutSet(a.getShortcutSet(), DiffModelTree.this); } }); setCellRenderer(new ColoredTreeCellRenderer() { @Override public void customizeCellRenderer(JTree p0, Object value, boolean p2, boolean p3, boolean p4, int p5, boolean p6) { if (value instanceof DiffModelTree.TreeNode) { ((DiffModelTree.TreeNode) value).renderTreeNode(this); } } }); setPopupGroup(ActionUtils.groupFromActions(Sequence.fromIterable(myActions).toGenericArray(BaseAction.class)), ActionPlaces.CHANGES_VIEW_POPUP); // listen for selection changes getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { DiffModelTree.RootTreeNode[] node = getSelectedNodes(DiffModelTree.RootTreeNode.class, null); if (node == null || node.length != 1) { onUnselect(); } else { onSelectRoot(node[0].getRootId()); } } }); } protected DiffModelTree.TreeNode rebuild() { DiffModelTree.ModelTreeNode modelNode = new DiffModelTree.ModelTreeNode(); myRootNodes = Sequence.fromIterable(getAffectedRoots()).where(new IWhereFilter<SNodeId>() { public boolean accept(SNodeId r) { return r != null; } }).select(new ISelector<SNodeId, DiffModelTree.RootTreeNode>() { public DiffModelTree.RootTreeNode select(SNodeId r) { return new DiffModelTree.RootTreeNode(r); } }).sort(new ISelector<DiffModelTree.RootTreeNode, String>() { public String select(DiffModelTree.RootTreeNode rtn) { return rtn.myVirtualPackage + "|" + rtn.myPresentation; } }, true).toListSequence(); for (DiffModelTree.RootTreeNode rtn : ListSequence.fromList(myRootNodes)) { DiffModelTree.TreeNode parentNode = modelNode; if (isNotEmptyString(rtn.myVirtualPackage)) { for (final String sub : Sequence.fromArray(rtn.myVirtualPackage.split("\\."))) { Iterable<DiffModelTree.TreeNode> children = Collections.list(parentNode.children()); DiffModelTree.TreeNode child = Sequence.fromIterable(children).findFirst(new IWhereFilter<DiffModelTree.TreeNode>() { public boolean accept(DiffModelTree.TreeNode c) { return c instanceof DiffModelTree.PackageTreeNode && sub.equals(c.getText()); } }); if (child == null) { child = new DiffModelTree.PackageTreeNode(sub); parentNode.add(child); } parentNode = child; } } parentNode.add(rtn); } if (Sequence.fromIterable(getAffectedRoots()).any(new IWhereFilter<SNodeId>() { public boolean accept(SNodeId r) { return r == null; } })) { DiffModelTree.RootTreeNode metadataNode = new DiffModelTree.MetadataTreeNode(); ListSequence.fromList(myRootNodes).addElement(metadataNode); modelNode.add(metadataNode); } return modelNode; } public void setSelected(@Nullable SNodeId rootId) { // todo: find path by rootId TreePath path = null; for (int i = 0; i < getRowCount(); ++i) { DiffModelTree.RootTreeNode node = as_5x0uld_a0a0a2a5(getPathForRow(i).getLastPathComponent(), DiffModelTree.RootTreeNode.class); if (node != null && eq_5x0uld_a0a1a2a5(node.getRootId(), rootId)) { path = getPathForRow(i); break; } } if (path != null) { expandPath(path); setSelectionPath(path); scrollPathToVisible(path); } } public void rebuildLater() { rebuildNow(); } public void rebuildNow() { ModelAccess.instance().runReadAction(new Runnable() { public void run() { setModel(new DefaultTreeModel(rebuild())); setRootVisible(true); TreeUtil.expandAll(DiffModelTree.this); setSelectionRow(0); } }); } protected abstract Iterable<SNodeId> getAffectedRoots(); protected abstract Iterable<SModel> getModels(); protected abstract void updateRootCustomPresentation(@NotNull DiffModelTree.RootTreeNode rootTreeNode); protected abstract Iterable<BaseAction> getRootActions(); protected boolean isMultipleRootNames() { return false; } protected void onUnselect() { } protected void onSelectRoot(@Nullable SNodeId rootId) { } private DiffModelTree.RootTreeNode findRootNode(@Nullable final SNodeId nodeId) { return ListSequence.fromList(myRootNodes).findFirst(new IWhereFilter<DiffModelTree.RootTreeNode>() { public boolean accept(DiffModelTree.RootTreeNode r) { return eq_5x0uld_a0a0a0a0a0a0p(nodeId, r.myRootId); } }); } private int advanceIndex(int index, boolean next) { return (next ? index + 1 : index - 1); } public boolean hasNeighbour(SNodeId nodeId, boolean next) { int index = advanceIndex(ListSequence.fromList(myRootNodes).indexOf(findRootNode(nodeId)), next); return index >= 0 && index < ListSequence.fromList(myRootNodes).count(); } @Nullable public SNodeId getNeighbourRoot(@Nullable SNodeId nodeId, boolean next) { int index = advanceIndex(ListSequence.fromList(myRootNodes).indexOf(findRootNode(nodeId)), next); assert index >= 0 && index < ListSequence.fromList(myRootNodes).count(); return ListSequence.fromList(myRootNodes).getElement(index).myRootId; } public String getNameForRoot(@Nullable SNodeId nodeId) { return check_5x0uld_a0a91(findRootNode(nodeId), this); } @Nullable @Override public Object getData(@NonNls String dataId) { if (NODE_ID_DATAKEY.is(dataId)) { DiffModelTree.RootTreeNode[] selectedNodes = getSelectedNodes(DiffModelTree.RootTreeNode.class, null); if (selectedNodes != null && selectedNodes.length > 0) { return new Ref<SNodeId>(selectedNodes[0].getRootId()); } } return null; } public class ModelTreeNode extends DiffModelTree.TreeNode { public ModelTreeNode() { setText("model"); setText(SModelOperations.getModelName(Sequence.fromIterable(getModels()).first())); setIcon(IdeIcons.MODEL_ICON); } } private class PackageTreeNode extends DiffModelTree.TreeNode { private PackageTreeNode(String packageName) { setText(packageName); } } public class RootTreeNode extends DiffModelTree.TreeNode { private SNodeId myRootId; private String myPresentation = null; private String myVirtualPackage = null; public RootTreeNode(SNodeId rootId) { myRootId = rootId; setText("" + myRootId); doUpdatePresentation(); } @Override protected void doUpdatePresentation() { myPresentation = null; Icon icon = null; for (SModel model : Sequence.fromIterable(getModels())) { SNode root = model.getNode(myRootId); if (root != null && SNodeOperations.getParent(root) == null) { String presentation = root.getPresentation(); if (myPresentation == null) { myPresentation = presentation; } else if (isMultipleRootNames()) { if (("/ " + myPresentation + " /").contains("/ " + presentation + " /")) { } else { myPresentation += " / " + presentation; } } if (myVirtualPackage == null) { myVirtualPackage = (SPropertyOperations.getString(root, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x115eca8579fL, "virtualPackage")) == null ? "" : SPropertyOperations.getString(root, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x115eca8579fL, "virtualPackage"))); } if (icon == null) { icon = IconManager.getIconFor(root); } } } setText(myPresentation); setIcon(icon); updateRootCustomPresentation(this); } @Nullable public SNodeId getRootId() { return myRootId; } public String getPresentation() { return myPresentation; } } public class MetadataTreeNode extends DiffModelTree.RootTreeNode { public MetadataTreeNode() { super(null); setText("metadata"); doUpdatePresentation(); } @Override protected void doUpdatePresentation() { setText("Model Properties"); setIcon(IdeIcons.PROPERTIES_ICON); updateRootCustomPresentation(this); } @Override public String getPresentation() { return "Model Properties"; } } public class TreeNode extends DefaultMutableTreeNode { private String myText; private int myTextStyle = SimpleTextAttributes.STYLE_PLAIN; private String myAdditionalText; private String myTooltipText; private Icon myIcon; private Color myColor; public TreeNode() { } public void renderTreeNode(ColoredTreeCellRenderer coloredRenderer) { ModelAccess.instance().runReadAction(new Runnable() { public void run() { doUpdatePresentation(); } }); coloredRenderer.append(getText(), new SimpleTextAttributes(myTextStyle, getColor())); if ((myAdditionalText != null && myAdditionalText.length() > 0)) { coloredRenderer.append(" (" + myAdditionalText + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, Color.GRAY)); } coloredRenderer.setToolTipText(myTooltipText); coloredRenderer.setIcon(getIcon()); } protected void doUpdatePresentation() { } public String getText() { return myText; } public void setText(String text) { myText = text; } public String getAdditionalText() { return myAdditionalText; } public void setAdditionalText(String additionalText) { myAdditionalText = additionalText; } public String getTooltipText() { return myTooltipText; } public void setTooltipText(String tooltipText) { myTooltipText = tooltipText; } public Icon getIcon() { return myIcon; } public void setIcon(Icon icon) { myIcon = icon; } public Color getColor() { return myColor; } public void setColor(Color color) { myColor = color; } public void setTextStyle(int textStyle) { myTextStyle = textStyle; } } private static String check_5x0uld_a0a91(DiffModelTree.RootTreeNode checkedDotOperand, DiffModelTree checkedDotThisExpression) { if (null != checkedDotOperand) { return checkedDotOperand.getPresentation(); } return null; } private static boolean isNotEmptyString(String str) { return str != null && str.length() > 0; } private static <T> T as_5x0uld_a0a0a2a5(Object o, Class<T> type) { return (type.isInstance(o) ? (T) o : null); } private static boolean eq_5x0uld_a0a1a2a5(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } private static boolean eq_5x0uld_a0a0a0a0a0a0p(Object a, Object b) { return (a != null ? a.equals(b) : a == b); } }