package jetbrains.mps.ide.actions; /*Generated by MPS */ import javax.swing.JPanel; import com.intellij.openapi.ui.ComboBox; import javax.swing.JLabel; import jetbrains.mps.ide.embeddableEditor.EmbeddableEditor; import com.intellij.openapi.ui.popup.JBPopup; import jetbrains.mps.project.Project; import java.util.List; import org.jetbrains.mps.openapi.model.SNode; import java.util.ArrayList; import javax.swing.JComponent; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.CustomShortcutSet; import javax.swing.KeyStroke; import java.awt.event.KeyEvent; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.CompositeShortcutSet; import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import jetbrains.mps.openapi.editor.style.StyleRegistry; import java.awt.Color; import java.awt.BorderLayout; import javax.swing.BorderFactory; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.SideBorder; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Insets; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.ColoredListCellRenderer; import javax.swing.JList; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import java.awt.Dimension; import com.intellij.openapi.Disposable; import javax.swing.Icon; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.ide.icons.IconManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import jetbrains.mps.openapi.navigation.NavigationSupport; public class ShowImplementationComponent extends JPanel { private ComboBox myNodeChooser; private JLabel myLocationLabel = new JLabel(""); private JLabel myCountLabel = new JLabel("0 of 0"); private EmbeddableEditor myEditor; private int mySelectedIndex = -1; private JBPopup myPopup; private Project myProject; private List<ShowImplementationComponent.ImplementationNode> myImplNodes; public ShowImplementationComponent(List<SNode> nodes, Project project) { project.getModelAccess().checkReadAccess(); myImplNodes = new ArrayList<ShowImplementationComponent.ImplementationNode>(nodes.size()); for (SNode node : nodes) { myImplNodes.add(new ShowImplementationComponent.ImplementationNode(node)); } myProject = project; myEditor = new EmbeddableEditor(myProject, false); myEditor.editNode(myImplNodes.get(0).myNode); init(); if (myImplNodes.size() > 0) { myNodeChooser.setSelectedIndex(0); } } public void setPopup(JBPopup popup) { myPopup = popup; } public JComponent getPreferredFocusableComponent() { return myNodeChooser; } private boolean isDisposed = false; public void dispose() { if (isDisposed) { return; } isDisposed = true; for (ShowImplementationComponent.ImplementationNode node : myImplNodes) { node.dispose(); } myEditor.disposeEditor(); } private ActionToolbar createToolbar() { DefaultActionGroup group = new DefaultActionGroup(); ShowImplementationComponent.BackAction back = new ShowImplementationComponent.BackAction(); back.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), this); group.add(back); ShowImplementationComponent.ForwardAction forward = new ShowImplementationComponent.ForwardAction(); forward.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), this); group.add(forward); ShowImplementationComponent.ShowSourceAction showSource = new ShowImplementationComponent.ShowSourceAction("Edit Source", AllIcons.Actions.EditSource, true); showSource.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0)), this); group.add(showSource); showSource = new ShowImplementationComponent.ShowSourceAction("Show Source", AllIcons.Actions.ShowViewer, false); // TODO: choose better icon showSource.registerCustomShortcutSet(new CompositeShortcutSet(CommonShortcuts.getViewSource(), CommonShortcuts.CTRL_ENTER), this); group.add(showSource); return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true); } private void updateControls() { final int index = myNodeChooser.getSelectedIndex(); if (index == -1) { return; } if (mySelectedIndex == index) { return; } myProject.getModelAccess().executeCommandInEDT(new Runnable() { @Override public void run() { myLocationLabel.setText(myImplNodes.get(index).myModuleName); myLocationLabel.setIcon(myImplNodes.get(index).myModuleIcon); myCountLabel.setText((index + 1) + " of " + myImplNodes.size()); myEditor.editNode(myImplNodes.get(index).myNode); myEditor.setBackground((StyleRegistry.getInstance().isDarkTheme() ? StyleRegistry.getInstance().getEditorBackground() : new Color(255, 255, 215))); mySelectedIndex = index; myEditor.repaint(); myNodeChooser.updateUI(); } }); } private void init() { setLayout(new BorderLayout()); add(myEditor, BorderLayout.CENTER); JPanel northPanel = new JPanel(new BorderLayout(2, 0)); northPanel.setBorder(BorderFactory.createCompoundBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM), IdeBorderFactory.createEmptyBorder(0, 0, 0, 5))); JPanel toolbarPanel = new JPanel(new GridBagLayout()); final GridBagConstraints gc = new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0); toolbarPanel.add(createToolbar().getComponent(), gc); this.myNodeChooser = new ComboBox(new CollectionComboBoxModel(myImplNodes, null)); myNodeChooser.setRenderer(new ColoredListCellRenderer() { @Override protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (!((value instanceof ShowImplementationComponent.ImplementationNode))) { return; } ShowImplementationComponent.ImplementationNode node = (ShowImplementationComponent.ImplementationNode) value; setIcon(node.myNodeIcon); append(node.myNodePresentation); } }); myNodeChooser.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { ShowImplementationComponent.this.updateControls(); } }); gc.fill = GridBagConstraints.HORIZONTAL; gc.weightx = 1; toolbarPanel.add(myNodeChooser, gc); gc.fill = GridBagConstraints.NONE; gc.weightx = 0; toolbarPanel.add(myCountLabel, gc); northPanel.add(toolbarPanel, BorderLayout.CENTER); northPanel.add(myLocationLabel, BorderLayout.EAST); add(northPanel, BorderLayout.NORTH); setPreferredSize(new Dimension(600, 400)); } private class ImplementationNode implements Disposable { public final SNode myNode; public final String myNodePresentation; public final Icon myNodeIcon; public final String myModuleName; public final Icon myModuleIcon; public final SNodeReference myOriginalNodePointer; public ImplementationNode(SNode node) { myNode = SNodeOperations.copyNode(((SNode) node)); myNodePresentation = (SNodeOperations.isInstanceOf(((SNode) node), MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b21dL, "jetbrains.mps.baseLanguage.structure.InstanceMethodDeclaration")) && node.getParent() != null ? node.getParent() + "." + node.getPresentation() : node.getPresentation()); myNodeIcon = IconManager.getIconFor(node); myModuleName = node.getModel().getModule().getModuleName(); myModuleIcon = IconManager.getIconFor(node.getModel().getModule()); myOriginalNodePointer = node.getReference(); } @Override public void dispose() { myNode.delete(); } } private class BackAction extends AnAction { public BackAction() { super("Back", null, AllIcons.Actions.Back); } @Override public void actionPerformed(AnActionEvent e) { assert myNodeChooser.getSelectedIndex() > 0; myNodeChooser.setSelectedIndex(myNodeChooser.getSelectedIndex() - 1); updateControls(); } @Override public void update(AnActionEvent e) { e.getPresentation().setEnabled(myNodeChooser != null && myNodeChooser.getSelectedIndex() > 0); } } private class ForwardAction extends AnAction { public ForwardAction() { super("Forward", null, AllIcons.Actions.Forward); } @Override public void actionPerformed(AnActionEvent e) { assert myNodeChooser.getSelectedIndex() < myNodeChooser.getItemCount() - 1; myNodeChooser.setSelectedIndex(myNodeChooser.getSelectedIndex() + 1); updateControls(); } @Override public void update(AnActionEvent e) { e.getPresentation().setEnabled(myNodeChooser != null && myNodeChooser.getSelectedIndex() < myNodeChooser.getItemCount() - 1); } } private class ShowSourceAction extends AnAction { private boolean myClosePopup; public ShowSourceAction(String name, Icon icon, boolean closePopup) { super(name, null, icon); myClosePopup = closePopup; } @Override public void actionPerformed(AnActionEvent e) { myProject.getModelAccess().runWriteInEDT(new Runnable() { @Override public void run() { int selectedIndex = myNodeChooser.getSelectedIndex(); if (selectedIndex < 0) { return; } SNode selectedNode = myImplNodes.get(selectedIndex).myOriginalNodePointer.resolve(myProject.getRepository()); if (selectedNode == null) { return; } NavigationSupport.getInstance().openNode(myProject, selectedNode, true, true); NavigationSupport.getInstance().selectInTree(myProject, selectedNode, false); if (myClosePopup) { myPopup.cancel(); } } }); } } }