diff options
author | Tor Norbye <tnorbye@google.com> | 2014-08-19 12:53:10 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2014-08-19 12:53:10 -0700 |
commit | 02cf98d65c798d368fcec43ed64a001d513bdd4f (patch) | |
tree | e39e210ab20917b7e5ffdce14a42f5747506eed0 /python/src/com/jetbrains/python/console | |
parent | 2e5965e996aad62ab1338b09d54caaf99ff3dd6a (diff) | |
download | idea-02cf98d65c798d368fcec43ed64a001d513bdd4f.tar.gz |
Snapshot idea/138.1503 from git://git.jetbrains.org/idea/community.git
Change-Id: Ie01af1d8710ec0ff51d90301bda1a18b0b5c0faf
Diffstat (limited to 'python/src/com/jetbrains/python/console')
4 files changed, 264 insertions, 20 deletions
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java index 3d77ac4f62b1..848818b95e27 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java @@ -16,6 +16,10 @@ package com.jetbrains.python.console; import com.google.common.base.CharMatcher; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionHelper; @@ -59,11 +63,14 @@ import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingManager; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.remote.RemoteSshProcess; import com.intellij.testFramework.LightVirtualFile; +import com.intellij.ui.content.Content; import com.intellij.util.ArrayUtil; import com.intellij.util.IJSwingUtilities; import com.intellij.util.PathMappingSettings; @@ -132,6 +139,9 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC private static final long APPROPRIATE_TO_WAIT = 60000; private PyRemoteSdkCredentials myRemoteCredentials; + private ToolWindow myToolWindow; + + private String myConsoleTitle = null; protected PydevConsoleRunner(@NotNull final Project project, @NotNull Sdk sdk, @NotNull final PyConsoleType consoleType, @@ -192,8 +202,10 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC @NotNull final PyConsoleType consoleType, @Nullable final String workingDirectory, @NotNull final Map<String, String> environmentVariables, + @Nullable final ToolWindow toolWindow, final String... statements2execute) { final PydevConsoleRunner consoleRunner = create(project, sdk, consoleType, workingDirectory, environmentVariables); + consoleRunner.setToolWindow(toolWindow); consoleRunner.setStatementsToExecute(statements2execute); consoleRunner.run(); return consoleRunner; @@ -481,6 +493,20 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC } } + @Override + protected String constructConsoleTitle(@NotNull String consoleTitle) { + if (myConsoleTitle == null) { + myConsoleTitle = super.constructConsoleTitle(consoleTitle); + } + return myConsoleTitle; + } + + @Override + protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) { + PythonConsoleToolWindow terminalView = PythonConsoleToolWindow.getInstance(getProject()); + terminalView.init(getToolWindow(), contentDescriptor); + } + protected AnAction createRerunAction() { return new RestartAction(this); } @@ -583,9 +609,32 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC } @Override - protected AnAction createCloseAction(Executor defaultExecutor, RunContentDescriptor myDescriptor) { - final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, myDescriptor); - return createConsoleStoppingAction(generalCloseAction); + protected AnAction createCloseAction(Executor defaultExecutor, final RunContentDescriptor descriptor) { + final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, descriptor); + + final AnAction stopAction = new DumbAwareAction() { + @Override + public void update(AnActionEvent e) { + generalCloseAction.update(e); + } + + @Override + public void actionPerformed(AnActionEvent e) { + e = stopConsole(e); + + clearContent(descriptor); + + generalCloseAction.actionPerformed(e); + } + }; + stopAction.copyFrom(generalCloseAction); + return stopAction; + } + + private void clearContent(RunContentDescriptor descriptor) { + Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName()); + assert content != null; + getToolWindow().getContentManager().removeContent(content, true); } private AnAction createConsoleStoppingAction(final AnAction generalStopAction) { @@ -597,26 +646,31 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC @Override public void actionPerformed(AnActionEvent e) { - if (myPydevConsoleCommunication != null) { - final AnActionEvent furtherActionEvent = - new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(), - e.getPresentation(), e.getActionManager(), e.getModifiers()); - try { - closeCommunication(); - // waiting for REPL communication before destroying process handler - Thread.sleep(300); - } - catch (Exception ignored) { - // Ignore - } - generalStopAction.actionPerformed(furtherActionEvent); - } + e = stopConsole(e); + + generalStopAction.actionPerformed(e); } }; stopAction.copyFrom(generalStopAction); return stopAction; } + private AnActionEvent stopConsole(AnActionEvent e) { + if (myPydevConsoleCommunication != null) { + e = new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(), + e.getPresentation(), e.getActionManager(), e.getModifiers()); + try { + closeCommunication(); + // waiting for REPL communication before destroying process handler + Thread.sleep(300); + } + catch (Exception ignored) { + // Ignore + } + } + return e; + } + protected AnAction createSplitLineAction() { class ConsoleSplitLineAction extends EditorAction { @@ -738,6 +792,17 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC } } + public ToolWindow getToolWindow() { + if (myToolWindow == null) { + myToolWindow = ToolWindowManager.getInstance(getProject()).getToolWindow(PythonConsoleToolWindowFactory.ID); + } + return myToolWindow; + } + + public void setToolWindow(ToolWindow toolWindow) { + myToolWindow = toolWindow; + } + public interface ConsoleListener { void handleConsoleInitialized(LanguageConsoleView consoleView); } @@ -889,4 +954,21 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC return session; } + + @Override + protected List<String> getActiveConsoleNames(final String consoleTitle) { + return FluentIterable.from( + Lists.newArrayList(PythonConsoleToolWindow.getInstance(getProject()).getToolWindow().getContentManager().getContents())).transform( + new Function<Content, String>() { + @Override + public String apply(Content input) { + return input.getDisplayName(); + } + }).filter(new Predicate<String>() { + @Override + public boolean apply(String input) { + return input.contains(consoleTitle); + } + }).toList(); + } } diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java new file mode 100644 index 000000000000..e8c50e49280a --- /dev/null +++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java @@ -0,0 +1,127 @@ +package com.jetbrains.python.console; + +import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.SimpleToolWindowPanel; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; +import com.intellij.openapi.wm.ex.ToolWindowManagerListener; +import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +/** + * @author traff + */ +public class PythonConsoleToolWindow { + + private final Project myProject; + + private boolean myInitialized = false; + + public PythonConsoleToolWindow(Project project) { + myProject = project; + } + + public static PythonConsoleToolWindow getInstance(@NotNull Project project) { + return project.getComponent(PythonConsoleToolWindow.class); + } + + + public void init(final @NotNull ToolWindow toolWindow, final @NotNull RunContentDescriptor contentDescriptor) { + addContent(toolWindow, contentDescriptor); + + if (!myInitialized) { + doInit(toolWindow); + } + } + + private void doInit(final ToolWindow toolWindow) { + myInitialized = true; + + toolWindow.setToHideOnEmptyContent(true); + + ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerListener() { + @Override + public void toolWindowRegistered(@NotNull String id) { + } + + @Override + public void stateChanged() { + ToolWindow window = getToolWindow(); + if (window != null) { + boolean visible = window.isVisible(); + if (visible && toolWindow.getContentManager().getContentCount() == 0) { + RunPythonConsoleAction.runPythonConsole(myProject, null, toolWindow); + } + } + } + }); + } + + private static void addContent(ToolWindow toolWindow, RunContentDescriptor contentDescriptor) { + toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true"); + + Content content = toolWindow.getContentManager().findContent(contentDescriptor.getDisplayName()); + if (content == null) { + content = createContent(contentDescriptor); + toolWindow.getContentManager().addContent(content); + } + else { + SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true); + resetContent(contentDescriptor, panel, content); + } + + toolWindow.getContentManager().setSelectedContent(content); + } + + public ToolWindow getToolWindow() { + return ToolWindowManager.getInstance(myProject).getToolWindow(PythonConsoleToolWindowFactory.ID); + } + + private static Content createContent(final @NotNull RunContentDescriptor contentDescriptor) { + SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true); + + final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, contentDescriptor.getDisplayName(), false); + content.setCloseable(true); + + resetContent(contentDescriptor, panel, content); + + return content; + } + + private static void resetContent(RunContentDescriptor contentDescriptor, SimpleToolWindowPanel panel, Content content) { + panel.setContent(contentDescriptor.getComponent()); + //panel.addFocusListener(createFocusListener(toolWindow)); + + content.setComponent(panel); + content.setPreferredFocusableComponent(contentDescriptor.getComponent()); + } + + private static FocusListener createFocusListener(final ToolWindow toolWindow) { + return new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + JComponent component = getComponentToFocus(toolWindow); + if (component != null) { + component.requestFocusInWindow(); + } + } + + @Override + public void focusLost(FocusEvent e) { + + } + }; + } + + private static JComponent getComponentToFocus(ToolWindow window) { + return window.getContentManager().getComponent(); + } +} diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java new file mode 100644 index 000000000000..f042a539bc22 --- /dev/null +++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2014 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 com.jetbrains.python.console; + +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowFactory; + +/** + * @author traff + */ +public class PythonConsoleToolWindowFactory implements ToolWindowFactory, DumbAware { + public static final String ID = "Python Console"; + + @Override + public void createToolWindowContent(Project project, ToolWindow toolWindow) { + RunPythonConsoleAction.runPythonConsole(project, null, toolWindow); + } +} diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java index 02a153f7a016..566adea43c87 100644 --- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java +++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java @@ -32,6 +32,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ToolWindow; import com.intellij.util.PathMappingSettings; import com.jetbrains.python.buildout.BuildoutFacet; import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; @@ -42,6 +43,7 @@ import com.jetbrains.python.sdk.PythonEnvUtil; import com.jetbrains.python.sdk.PythonSdkType; import icons.PythonIcons; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; @@ -77,11 +79,11 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware { public void actionPerformed(final AnActionEvent e) { final Project project = e.getData(CommonDataKeys.PROJECT); - runPythonConsole(project, e.getData(LangDataKeys.MODULE)); + runPythonConsole(project, e.getData(LangDataKeys.MODULE), null); } @NotNull - public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule) { + public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule, @Nullable ToolWindow toolWindow) { assert project != null : "Project is null"; Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule); @@ -152,7 +154,7 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware { envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled); return PydevConsoleRunner - .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, setupFragment); + .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, toolWindow, setupFragment); } public static PathMappingSettings getMappings(Project project, Sdk sdk) { |