package jetbrains.mps.debugger.api.ui.breakpoints; /*Generated by MPS */ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.actionSystem.DataProvider; import javax.swing.JPanel; import javax.swing.JComponent; import jetbrains.mps.project.Project; import jetbrains.mps.debug.api.BreakpointManagerComponent; import jetbrains.mps.debug.api.breakpoints.BreakpointProvidersManager; import javax.swing.JScrollPane; import java.util.Map; import jetbrains.mps.debug.api.breakpoints.IBreakpointKind; import jetbrains.mps.debug.api.breakpoints.IBreakpointPropertiesUi; import java.util.HashMap; import jetbrains.mps.debug.api.breakpoints.IBreakpoint; import jetbrains.mps.ide.project.ProjectHelper; import java.awt.BorderLayout; import com.intellij.ui.ScrollPaneFactory; import javax.swing.UIManager; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import java.awt.Dimension; import jetbrains.mps.debug.api.breakpoints.IBreakpointsProvider; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.DefaultActionGroup; import jetbrains.mps.workbench.action.BaseAction; import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.actionSystem.ToggleAction; import jetbrains.mps.debugger.api.ui.icons.Icons; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.AnAction; import javax.swing.AbstractAction; import java.awt.event.ActionEvent; import javax.swing.KeyStroke; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import com.intellij.ide.DataManager; import jetbrains.mps.debug.api.breakpoints.ILocationBreakpoint; import jetbrains.mps.openapi.navigation.EditorNavigator; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.Action; public class BreakpointsBrowserDialog extends DialogWrapper implements DataProvider { private static final String COMMAND_SHOW_NODE = "COMMAND_SHOW_NODE"; private final JPanel myMainPanel; private JComponent myPropertiesEditorPanel; private final Project myProject; private final BreakpointManagerComponent myBreakpointsManager; private final BreakpointProvidersManager myProvidersManager; private final BreakpointsUiComponent myBreakpointsUi; private final JScrollPane myBreakpointsScrollPane; private final BreakpointsView[] myViews; private int myCurrentViewIndex; private final Map<IBreakpointKind, IBreakpointPropertiesUi> myKindToUi = new HashMap<IBreakpointKind, IBreakpointPropertiesUi>(); private final BreakpointManagerComponent.BreakpointManagerListener myBreakpointManagerListener = new BreakpointManagerComponent.BreakpointManagerListener() { @Override public void breakpointsChanged() { IBreakpoint bp = myViews[myCurrentViewIndex].getSelectedBreakpoint(); breakpointSelected(bp); } }; public BreakpointsBrowserDialog(Project mpsProject) { super(ProjectHelper.toIdeaProject(mpsProject)); setTitle("Breakpoints"); setModal(false); this.setOKButtonText("Close"); myProject = mpsProject; myBreakpointsManager = BreakpointManagerComponent.getInstance(ProjectHelper.toIdeaProject(mpsProject)); myBreakpointsUi = BreakpointsUiComponent.getInstance(ProjectHelper.toIdeaProject(mpsProject)); myProvidersManager = BreakpointProvidersManager.getInstance(); myCurrentViewIndex = BreakpointViewSettingsComponent.getInstance(mpsProject).getViewIndex(); myViews = new BreakpointsView[]{new BreakpointsTable(mpsProject, myBreakpointsManager), new BreakpointsTree(mpsProject, myBreakpointsManager)}; myMainPanel = new JPanel(new BorderLayout()); myBreakpointsScrollPane = ScrollPaneFactory.createScrollPane(myViews[myCurrentViewIndex].getMainComponent()); myBreakpointsScrollPane.getViewport().setBackground(UIManager.getColor("Table.background")); myMainPanel.add(myBreakpointsScrollPane, BorderLayout.CENTER); ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, createActionGroup(), true); myMainPanel.add(actionToolbar.getComponent(), BorderLayout.NORTH); myMainPanel.setMinimumSize(new Dimension(500, 500)); // register keyboard/mouse actions on all views registerActionsOnViews(); initPropertiesUi(); init(); } private void saveState() { if (myProject.isDisposed()) { return; } for (BreakpointsView view : myViews) { view.saveState(); } } private void initPropertiesUi() { for (IBreakpointKind kind : myProvidersManager.getAllKinds()) { IBreakpointsProvider provider = myProvidersManager.getProvider(kind); if (provider == null) { continue; } IBreakpointPropertiesUi editor = provider.createPropertiesEditor(kind); if (editor == null) { continue; } myKindToUi.put(kind, editor); } for (BreakpointsView view : myViews) { view.addBreakpointSelectionListener(new BreakpointsView.BreakpointSelectionListener() { @Override public void breakpointSelected(@Nullable IBreakpoint breakpoint) { BreakpointsBrowserDialog.this.breakpointSelected(breakpoint); } }); } myBreakpointsManager.addChangeListener(myBreakpointManagerListener); IBreakpoint selectedBreakpoint = myViews[myCurrentViewIndex].getSelectedBreakpoint(); if (selectedBreakpoint != null) { breakpointSelected(selectedBreakpoint); } } public void selectBreakpoint(@Nullable IBreakpoint breakpoint) { myViews[myCurrentViewIndex].selectBreakpoint(breakpoint); } private void breakpointSelected(IBreakpoint breakpoint) { if (myPropertiesEditorPanel != null) { myMainPanel.remove(myPropertiesEditorPanel); } if (breakpoint != null) { IBreakpointPropertiesUi ui = myKindToUi.get(breakpoint.getKind()); if (ui != null) { ui.setBreakpoint(breakpoint); myPropertiesEditorPanel = ui.getMainComponent(); myMainPanel.add(myPropertiesEditorPanel, BorderLayout.SOUTH); } } myMainPanel.updateUI(); } private ActionGroup createActionGroup() { // create actions DefaultActionGroup group = new DefaultActionGroup(); group.add(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.GoToBreakpointSourceAction_Action"))); group.add(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.ViewBreakpointSourceAction_Action"))); group.add(createAddActionGroup()); group.add(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.DeleteBreakpointAction_Action"))); group.add(new Separator()); group.add(new ToggleAction("Tree View", "Toggle Tree/List View", Icons.BREAKPOINTS_DIALOG_TREE_VIEW) { @Override public boolean isSelected(AnActionEvent e) { return isTreeView(); } @Override public void setSelected(AnActionEvent e, boolean state) { switchView(); e.getPresentation().setText(myViews[1 - myCurrentViewIndex].getTitle()); } }); group.add(new ToggleAction("Group By Module", "Group By Module", Icons.BREAKPOINTS_DIALOG_GROUP_BY_MODULE) { @Override public void update(AnActionEvent e) { super.update(e); e.getPresentation().setEnabled(isTreeView()); } @Override public boolean isSelected(AnActionEvent e) { if (!(isTreeView())) { return false; } BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; return tree.isModuleGroupVisible(); } @Override public void setSelected(AnActionEvent e, boolean state) { BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; tree.toggleModuleGroup(state); tree.update(); } }); group.add(new ToggleAction("Group By Model", "Group By Model", Icons.BREAKPOINTS_DIALOG_GROUP_BY_MODEL) { @Override public void update(AnActionEvent e) { super.update(e); e.getPresentation().setEnabled(isTreeView()); } @Override public boolean isSelected(AnActionEvent e) { if (!(isTreeView())) { return false; } BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; return tree.isModelGroupVisible(); } @Override public void setSelected(AnActionEvent e, boolean state) { BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; tree.toggleModelGroup(state); tree.update(); } }); group.add(new ToggleAction("Group By Root", "Group By Root", Icons.BREAKPOINTS_DIALOG_GROUP_BY_ROOT) { @Override public void update(AnActionEvent e) { super.update(e); e.getPresentation().setEnabled(isTreeView()); } @Override public boolean isSelected(AnActionEvent e) { if (!(isTreeView())) { return false; } BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; return tree.isRootGroupVisible(); } @Override public void setSelected(AnActionEvent e, boolean state) { BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; tree.toggleRootGroup(state); tree.update(); } }); group.add(new AnAction("Expand All", "Expand All", jetbrains.mps.ide.findusages.view.icons.Icons.EXPAND_ICON) { @Override public void update(AnActionEvent e) { // todo refactor actions: each view should provide their own actions e.getPresentation().setEnabled(isTreeView()); } @Override public void actionPerformed(AnActionEvent e) { if (!(isTreeView())) { return; } BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; tree.expandAll(); } }); group.add(new AnAction("Collapse All", "Collapse All", jetbrains.mps.ide.findusages.view.icons.Icons.COLLAPSE_ICON) { @Override public void update(AnActionEvent e) { e.getPresentation().setEnabled(isTreeView()); } @Override public void actionPerformed(AnActionEvent e) { if (!(isTreeView())) { return; } BreakpointsTree tree = (BreakpointsTree) myViews[myCurrentViewIndex]; tree.collapseAll(); } }); return group; } private DefaultActionGroup createAddActionGroup() { DefaultActionGroup addActionGroup = new DefaultActionGroup("Add Breakpoint", true) { @Override public void update(AnActionEvent e) { super.update(e); e.getPresentation().setIcon(Icons.BREAKPOINTS_DIALOG_ADD); } }; for (final IBreakpointKind kind : myProvidersManager.getAllKinds()) { IBreakpointsProvider provider = myProvidersManager.getProvider(kind); if (provider != null && provider.canCreateFromUi(kind)) { // TODO can't we ask this from kind?? AnAction addBreakpoointAction = new AnAction(kind.getPresentation(), "Create " + kind.getPresentation(), null) { @Override public void actionPerformed(AnActionEvent e) { myBreakpointsUi.createFromUi(kind); } }; addActionGroup.add(addBreakpoointAction); } } return addActionGroup; } private IBreakpoint getBreakpoint(AnActionEvent e) { return BreakpointsUtil.MPS_BREAKPOINT.getData(e.getDataContext()); } private boolean isTreeView() { return myViews[myCurrentViewIndex] instanceof BreakpointsTree; } private void switchView() { myCurrentViewIndex = 1 - myCurrentViewIndex; BreakpointViewSettingsComponent.getInstance(myProject).setViewIndex(myCurrentViewIndex); myBreakpointsScrollPane.setViewportView(myViews[myCurrentViewIndex].getMainComponent()); } protected AbstractAction createWrapper(final AnAction action) { return new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { action.actionPerformed(createEvent(action)); } }; } private void registerActionsOnViews() { for (BreakpointsView myView : myViews) { // show on enter myView.getMainComponent().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), COMMAND_SHOW_NODE); myView.getMainComponent().getActionMap().put(COMMAND_SHOW_NODE, createWrapper(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.ViewBreakpointSourceAction_Action")))); // open on f4 myView.getMainComponent().registerKeyboardAction(createWrapper(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.GoToBreakpointSourceAction_Action"))), KeyStroke.getKeyStroke("F4"), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); // delete on del myView.getMainComponent().registerKeyboardAction(createWrapper(((BaseAction) ActionManager.getInstance().getAction("jetbrains.mps.debugger.api.ui.actions.DeleteBreakpointAction_Action"))), KeyStroke.getKeyStroke("DELETE"), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); // open on double click myView.getMainComponent().addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { IBreakpoint breakpoint = BreakpointsUtil.MPS_BREAKPOINT.getData(myViews[myCurrentViewIndex]); if (breakpoint == null) { return; } dispose(); openNode(breakpoint, true, true); } } }); } } private AnActionEvent createEvent(AnAction action) { return new AnActionEvent(null, DataManager.getInstance().getDataContext(this.getContentPane()), ActionPlaces.UNKNOWN, action.getTemplatePresentation(), ActionManager.getInstance(), 0); } private void openNode(IBreakpoint breakpoint, boolean focus, boolean select) { if (!((breakpoint instanceof ILocationBreakpoint))) { return; } new EditorNavigator(myProject).shallFocus(focus).shallSelect(select).open(((ILocationBreakpoint) breakpoint).getLocation().getNodePointer()); } @Nullable @Override protected JComponent createCenterPanel() { this.getWindow().addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { saveState(); } }); return myMainPanel; } @Nullable @NonNls @Override protected String getDimensionServiceKey() { return BreakpointsBrowserDialog.class.getName(); } @Override @NotNull protected Action[] createActions() { return new Action[]{getOKAction()}; } @Override @Nullable public Object getData(@NonNls String dataId) { if (BreakpointsUtil.MPS_BREAKPOINTS_BROWSER_DIALOG.is(dataId)) { return this; } return myViews[myCurrentViewIndex].getData(dataId); } @Override public void dispose() { for (BreakpointsView view : myViews) { view.dispose(); } myBreakpointsManager.removeChangeListener(myBreakpointManagerListener); super.dispose(); } }