package krasa.grepconsole.grep; import com.intellij.execution.ExecutionManager; import com.intellij.execution.impl.ConsoleViewImpl; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.*; import com.intellij.execution.ui.layout.impl.RunnerLayoutUiImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import krasa.grepconsole.filter.GrepCopyingFilter; import krasa.grepconsole.grep.gui.GrepPanel; import krasa.grepconsole.grep.listener.GrepCopyingFilterAsyncListener; import krasa.grepconsole.grep.listener.GrepCopyingFilterListener; import krasa.grepconsole.grep.listener.GrepCopyingFilterSyncListener; import krasa.grepconsole.grep.listener.Mode; import krasa.grepconsole.model.Profile; import krasa.grepconsole.plugin.GrepConsoleApplicationComponent; import krasa.grepconsole.plugin.ServiceManager; import krasa.grepconsole.utils.Utils; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.io.OutputStream; public class OpenGrepConsoleAction extends DumbAwareAction { public OpenGrepConsoleAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) { super(text, description, icon); } @Override public void actionPerformed(AnActionEvent e) { Project eventProject = getEventProject(e); ConsoleViewImpl originalConsoleView = (ConsoleViewImpl) getConsoleView(e); final GrepCopyingFilter copyingFilter = ServiceManager.getInstance().getCopyingFilter(originalConsoleView); if (copyingFilter == null) { throw new IllegalStateException("Console not supported: " + originalConsoleView); } String expression = getExpression(e); CopyListenerModel copyListenerModel = new CopyListenerModel(false, false, false, expression, null); RunnerLayoutUi runnerLayoutUi = getRunnerLayoutUi(eventProject, originalConsoleView, e.getDataContext()); LightProcessHandler myProcessHandler = new LightProcessHandler(); Profile profile = GrepConsoleApplicationComponent.getInstance().getProfile(); final GrepCopyingFilterListener copyingListener; Mode mode = Mode.SYNC; if (Mode.SYNC == mode) { copyingListener = new GrepCopyingFilterSyncListener(myProcessHandler, eventProject, profile); } else { copyingListener = new GrepCopyingFilterAsyncListener(myProcessHandler, eventProject, profile); } ConsoleViewImpl newConsole = (ConsoleViewImpl) createConsole(eventProject, myProcessHandler); DefaultActionGroup actions = new DefaultActionGroup(); final GrepPanel quickFilterPanel = new GrepPanel(originalConsoleView, newConsole, copyingListener, expression, runnerLayoutUi); final MyJPanel consolePanel = createConsolePanel(runnerLayoutUi, newConsole, actions, quickFilterPanel); for (AnAction action : newConsole.createConsoleActions()) { actions.add(action); } final Content tab = runnerLayoutUi.createContent(getContentType(runnerLayoutUi), consolePanel, title(expression), getTemplatePresentation().getSelectedIcon(), consolePanel); runnerLayoutUi.addContent(tab); runnerLayoutUi.selectAndFocus(tab, true, true); quickFilterPanel.setApplyCallback(new Callback() { @Override public void apply(CopyListenerModel copyListenerModel) { copyingListener.modelUpdated(copyListenerModel); tab.setDisplayName(title(copyListenerModel.getExpression())); } }); for (String s : originalConsoleView.getEditor().getDocument().getText().split("\n")) { copyingListener.process(s + "\n", ConsoleViewContentType.NORMAL_OUTPUT); } copyingFilter.addListener(copyingListener); RunContentDescriptor runContentDescriptor = getRunContentDescriptor(eventProject); if (runContentDescriptor != null) { Disposer.register(runContentDescriptor, tab); } Disposer.register(tab, consolePanel); Disposer.register(consolePanel, newConsole); Disposer.register(consolePanel, copyingListener); Disposer.register(consolePanel, quickFilterPanel); Disposer.register(consolePanel, new Disposable() { @Override public void dispose() { copyingFilter.removeListener(copyingListener); } }); Disposable inactiveTitleDisposer; Container parent = originalConsoleView.getParent(); if (parent instanceof MyJPanel && !Disposer.isDisposed((MyJPanel) parent)) { inactiveTitleDisposer = (MyJPanel) parent; } else { inactiveTitleDisposer = originalConsoleView; } Disposer.register(inactiveTitleDisposer, new Disposable() { @Override public void dispose() { // dispose chained grep consoles Disposer.dispose(quickFilterPanel); tab.setDisplayName(title(tab.getDisplayName()) + " (Inactive)"); } }); } protected String title(String expression) { return StringUtils.substring(expression, 0, 20); } @NotNull protected String getExpression(AnActionEvent e) { String s = Utils.getSelectedString(e); if (s == null) s = ""; if (s.endsWith("\n")) { s = s.substring(0, s.length() - 1); } return s; } @Nullable protected String getContentType(@NotNull RunnerLayoutUi runnerLayoutUi) { ContentManager contentManager = runnerLayoutUi.getContentManager(); Content selectedContent = contentManager.getSelectedContent(); return RunnerLayoutUiImpl.CONTENT_TYPE.get(selectedContent); } public interface Callback { void apply(CopyListenerModel copyListenerModel); } @Nullable private RunnerLayoutUi getRunnerLayoutUi(Project eventProject, ConsoleViewImpl originalConsoleView, DataContext dataContext) { RunnerLayoutUi runnerLayoutUi = null; final RunContentDescriptor selectedContent = getRunContentDescriptor(eventProject); if (selectedContent != null) { runnerLayoutUi = selectedContent.getRunnerLayoutUi(); } if (runnerLayoutUi == null) { XDebugSession debugSession = XDebuggerManager.getInstance(eventProject).getDebugSession( originalConsoleView); if (debugSession != null) { runnerLayoutUi = debugSession.getUI(); } if (debugSession == null) { XDebugSession currentSession = XDebuggerManager.getInstance(eventProject).getCurrentSession(); if (currentSession != null) { runnerLayoutUi = currentSession.getUI(); } } } if (runnerLayoutUi == null) { Container parent = originalConsoleView.getParent(); if (parent instanceof MyJPanel) { runnerLayoutUi = ((MyJPanel) parent).runnerLayoutUi; } } return runnerLayoutUi; } private RunContentDescriptor getRunContentDescriptor(Project eventProject) { RunContentManager contentManager = ExecutionManager.getInstance(eventProject).getContentManager(); return contentManager.getSelectedContent(); } public static class LightProcessHandler extends ProcessHandler { @Override protected void destroyProcessImpl() { throw new UnsupportedOperationException(); } @Override protected void detachProcessImpl() { throw new UnsupportedOperationException(); } @Override public boolean detachIsDefault() { return false; } @Override @Nullable public OutputStream getProcessInput() { return null; } } private static MyJPanel createConsolePanel(RunnerLayoutUi runnerLayoutUi, ConsoleView view, ActionGroup actions, GrepPanel comp) { MyJPanel panel = new MyJPanel(runnerLayoutUi); panel.setLayout(new BorderLayout()); panel.add(comp.getRootComponent(), BorderLayout.NORTH); panel.add(view.getComponent(), BorderLayout.CENTER); panel.add(createToolbar(actions), BorderLayout.WEST); return panel; } private static JComponent createToolbar(ActionGroup actions) { ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, false); return actionToolbar.getComponent(); } private ConsoleView createConsole(@NotNull Project project, @NotNull ProcessHandler processHandler) { ConsoleView console = ServiceManager.getInstance().createConsoleWithoutInputFilter(project); console.attachToProcess(processHandler); return console; } private ConsoleView getConsoleView(AnActionEvent e) { return e.getData(LangDataKeys.CONSOLE_VIEW); } @Override public void update(AnActionEvent e) { Presentation presentation = e.getPresentation(); boolean enabled = false; Project eventProject = getEventProject(e); ConsoleViewImpl originalConsoleView = (ConsoleViewImpl) getConsoleView(e); GrepCopyingFilter copyingFilter = ServiceManager.getInstance().getCopyingFilter(originalConsoleView); if (eventProject != null && copyingFilter != null) { RunnerLayoutUi runnerLayoutUi = getRunnerLayoutUi(eventProject, originalConsoleView, e.getDataContext()); enabled = runnerLayoutUi != null && getContentType(runnerLayoutUi) != null; } presentation.setEnabled(enabled); } static class MyJPanel extends JPanel implements Disposable { private RunnerLayoutUi runnerLayoutUi; public MyJPanel(RunnerLayoutUi runnerLayoutUi) { this.runnerLayoutUi = runnerLayoutUi; } @Override public void dispose() { runnerLayoutUi = null; //TODO leak when closing tail by Close button // myPreferredFocusableComponent com.intellij.ui.tabs.TabInfo removeAll(); } } }