Manage.py toolwindow refactored to share functionality with other toolwindows for...
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Thu, 9 Apr 2015 21:50:59 +0000 (00:50 +0300)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Thu, 9 Apr 2015 21:50:59 +0000 (00:50 +0300)
python/src/com/jetbrains/commandInterface/console/CommandConsole.java
python/src/com/jetbrains/commandInterface/console/CommandLineConsoleApi.java
python/src/com/jetbrains/commandInterface/console/ConsoleTabsPanel.java [deleted file]
python/src/com/jetbrains/python/PyBundle.properties
python/src/com/jetbrains/toolWindowWithActions/ConsoleStopProcessAction.java [new file with mode: 0644]
python/src/com/jetbrains/toolWindowWithActions/ConsoleWithProcess.java [new file with mode: 0644]
python/src/com/jetbrains/toolWindowWithActions/PanelWithActions.java [new file with mode: 0644]
python/src/com/jetbrains/toolWindowWithActions/ToolWindowApi.java [moved from python/src/com/jetbrains/commandInterface/console/ToolWindowApi.java with 96% similarity]
python/src/com/jetbrains/toolWindowWithActions/WindowWithActions.java [new file with mode: 0644]
python/src/com/jetbrains/toolWindowWithActions/package-info.java [new file with mode: 0644]

index 8fa4f62171d32d1ab6f432f54bce5fd7e191310a..66887e62d7e08cb1007950b6a6ab973ff4743029 100644 (file)
@@ -31,6 +31,7 @@ import com.jetbrains.commandInterface.command.Command;
 import com.jetbrains.commandInterface.commandLine.CommandLineLanguage;
 import com.jetbrains.commandInterface.commandLine.psi.CommandLineFile;
 import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.toolWindowWithActions.ConsoleWithProcess;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -62,7 +63,7 @@ import java.util.List;
  * @author Ilya.Kazakevich
  */
 @SuppressWarnings({"DeserializableClassInSecureContext", "SerializableClassInSecureContext"}) // Nobody will serialize console
-final class CommandConsole extends LanguageConsoleImpl implements Consumer<String>, Condition<LanguageConsoleView> {
+final class CommandConsole extends LanguageConsoleImpl implements Consumer<String>, Condition<LanguageConsoleView>, ConsoleWithProcess {
   /**
    * List of commands (to be injected into {@link CommandLineFile}) if any
    */
@@ -189,8 +190,9 @@ final class CommandConsole extends LanguageConsoleImpl implements Consumer<Strin
    * @return process handler currently running on console (if any) or null if in {@link #switchToCommandMode() command mode}
    * @see #switchToProcessMode(ProcessHandler)
    */
+  @Override
   @Nullable
-  ProcessHandler getProcessHandler() {
+  public ProcessHandler getProcessHandler() {
     return myProcessHandler;
   }
 
index 165a61ffb53d9063a1a38693eb835bd3aac1fb88..30d9d6910f8f21a905cff1610473080c832ca63b 100644 (file)
@@ -17,19 +17,12 @@ package com.jetbrains.commandInterface.console;
 
 import com.intellij.execution.console.LanguageConsoleBuilder;
 import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.wm.ToolWindow;
-import com.intellij.openapi.wm.ToolWindowAnchor;
-import com.intellij.openapi.wm.ToolWindowManager;
-import com.intellij.ui.content.Content;
-import com.intellij.ui.content.ContentManager;
-import com.intellij.ui.content.impl.ContentImpl;
 import com.intellij.util.Consumer;
 import com.jetbrains.commandInterface.command.Command;
+import com.jetbrains.toolWindowWithActions.WindowWithActions;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -64,30 +57,15 @@ public final class CommandLineConsoleApi {
     final Project project = module.getProject();
     final CommandConsole console = CommandConsole.createConsole(module, consoleName, commandList);
 
-    final ToolWindowApi windowApi = new ToolWindowApi(project, consoleName);
-    // Add console to the toolwindow wrapping it with tabs
-    windowApi.add(ConsoleTabsPanel.wrapConsole(console, new MyCloseDelegate(windowApi)));
+    // Show console on "toolwindow"
+    WindowWithActions.showConsoleWithProcess(console,
+                                             console.getEditor().getComponent(),
+                                             consoleName,
+                                             project,
+                                             null);
 
     ArgumentHintLayer.attach(console); // Display [arguments]
     return console;
   }
-
-  /**
-   * Console tabs needs so-called "closer": engine to be called when user wishes to close tabs.
-   * We need to delegate this call to the {@link ToolWindowApi#close()}  to close whole window
-   */
-  private static final class MyCloseDelegate implements Runnable {
-    @NotNull
-    private final ToolWindowApi myWindowApi;
-
-    private MyCloseDelegate(@NotNull final ToolWindowApi windowApi) {
-      myWindowApi = windowApi;
-    }
-
-    @Override
-    public void run() {
-      myWindowApi.close();
-    }
-  }
 }
 
diff --git a/python/src/com/jetbrains/commandInterface/console/ConsoleTabsPanel.java b/python/src/com/jetbrains/commandInterface/console/ConsoleTabsPanel.java
deleted file mode 100644 (file)
index 2319c6b..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2000-2015 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.commandInterface.console;
-
-import com.intellij.execution.actions.StopProcessAction;
-import com.intellij.execution.runners.AbstractConsoleRunnerWithHistory;
-import com.intellij.ide.actions.CloseAction;
-import com.intellij.openapi.actionSystem.*;
-import com.jetbrains.python.PyBundle;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-
-/**
- * Panel with action buttons that wraps {@link CommandConsole}.
- * Entry point is {@link #wrapConsole(CommandConsole, Runnable)}. You may then just add it to what ever you want.
- *
- * @author Ilya.Kazakevich
- */
-@SuppressWarnings({"DeserializableClassInSecureContext", "SerializableClassInSecureContext"}) // Who will serialize panel?
-final class ConsoleTabsPanel extends JPanel {
-  private ConsoleTabsPanel() {
-
-  }
-
-  /**
-   * Wraps console with panel with buttons returning composite component to add somewhere.
-   *
-   * @param console Console to wrap.
-   * @param closer  Listener to delegate "close all" command (when user clicks red cross aka "close" button)
-   * @return composite component with console on the right part and buttons on the left part
-   */
-  @NotNull
-  static JComponent wrapConsole(@NotNull final CommandConsole console, @NotNull final Runnable closer) {
-    final ConsoleTabsPanel instance = new ConsoleTabsPanel();
-
-    // Box layout: panel goes to the left, console to the right
-    final LayoutManager layout = new BoxLayout(instance, BoxLayout.LINE_AXIS);
-    instance.setLayout(layout);
-
-    // use actions from console itself
-    final List<AnAction> actionList = new ArrayList<AnAction>(Arrays.asList(console.createConsoleActions()));
-    actionList.add(new MyCloseAction(closer, console)); // "Close" action
-    actionList.add(new MyStopProcessAction(console)); // "Stop process" action
-
-
-    final DefaultActionGroup toolbarActions = new DefaultActionGroup(actionList);
-
-    final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, toolbarActions, false);
-    toolbar.setTargetComponent(console);
-
-    // TODO: Move GUI and alignment out of here.
-    final JComponent toolbarComponent = toolbar.getComponent();
-
-    toolbarComponent.setMaximumSize(toolbarComponent.getPreferredSize()); // To make actions panel as small as possible (not 50% of width)
-    toolbarComponent.setAlignmentY(0);  // Align actions to the top
-    instance.add(toolbarComponent);
-    instance.add(console.getComponent());
-    AbstractConsoleRunnerWithHistory.registerActionShortcuts(actionList, console.getConsoleEditor().getComponent());
-    return instance;
-  }
-
-  /**
-   * Closes console and notifies closer when user clicks "close"
-   */
-  private static final class MyCloseAction extends CloseAction {
-    @NotNull
-    private final Runnable myCloser;
-    @NotNull
-    private final CommandConsole myConsole;
-
-    /**
-     * @param closer engine to be called when user clicks "close"
-     * @param console console itself
-     */
-    MyCloseAction(@NotNull final Runnable closer, @NotNull final CommandConsole console) {
-      myCloser = closer;
-      myConsole = console;
-    }
-
-    @Override
-    public void update(final AnActionEvent e) {
-      super.update(e);
-      e.getPresentation().setText(PyBundle.message("commandLine.closeWindow"));
-    }
-
-    @Override
-    public void actionPerformed(final AnActionEvent e) {
-      super.actionPerformed(e);
-      StopProcessAction.stopProcess(myConsole.getProcessHandler()); // Stop process before closing console, no need to left junk
-      myCloser.run();
-    }
-  }
-
-  /**
-   * Stops currently running process (if any)
-   */
-  private static final class MyStopProcessAction extends StopProcessAction {
-    private final CommandConsole myConsole;
-
-    /**
-     * @param console command console where process takes place
-     */
-    private MyStopProcessAction(@NotNull final CommandConsole console) {
-      super(PyBundle.message("commandLine.stopProcess"), null, null);
-      myConsole = console;
-    }
-
-    @Override
-    public void update(final AnActionEvent e) {
-      super.update(e);
-      setProcessHandler(myConsole.getProcessHandler()); // Attach action to process handler (if any) or detach (if no process runs)
-    }
-  }
-}
index 33f8d8a17a385a458226c8883083e0050b4588fe..624ff1433c052d304bc8dbb7bc5b0e5df95d172b 100644 (file)
@@ -878,8 +878,9 @@ commandLine.inspection.excessArgument=Excess argument or argument is not possibl
 commandLine.argumentHint.defaultName=arguments
 # What to display of user entered junk
 commandLine.commandNotFound={0}: command not found
+
+# Window with actions
 # "X" button title
-commandLine.closeWindow=Close command line window
+windowWithActions.closeWindow=Close window
 # "Stop" button title
-commandLine.stopProcess=Stop currently running process
-
+windowWithActions.stopProcess=Stop currently running process
diff --git a/python/src/com/jetbrains/toolWindowWithActions/ConsoleStopProcessAction.java b/python/src/com/jetbrains/toolWindowWithActions/ConsoleStopProcessAction.java
new file mode 100644 (file)
index 0000000..c3af091
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2015 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.toolWindowWithActions;
+
+import com.intellij.execution.actions.StopProcessAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.jetbrains.python.PyBundle;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * "Stop" action that stops process, attached to console.
+ * It also stops process when {@link #run()} is called. Useful for cases like some "close listener"
+ *
+ * @author Ilya.Kazakevich
+ */
+final class ConsoleStopProcessAction extends StopProcessAction implements Runnable {
+  private final ConsoleWithProcess myConsole;
+
+
+  ConsoleStopProcessAction(@NotNull final ConsoleWithProcess console) {
+    super(PyBundle.message("windowWithActions.stopProcess"), null, null);
+    myConsole = console;
+  }
+
+  @Override
+  public void update(final AnActionEvent e) {
+    super.update(e);
+    setProcessHandler(myConsole.getProcessHandler()); // Attach action to process handler (if any) or detach (if no process runs)
+  }
+
+
+  @Override
+  public void run() {
+    stopProcess(myConsole.getProcessHandler());
+  }
+}
diff --git a/python/src/com/jetbrains/toolWindowWithActions/ConsoleWithProcess.java b/python/src/com/jetbrains/toolWindowWithActions/ConsoleWithProcess.java
new file mode 100644 (file)
index 0000000..402c29b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2015 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.toolWindowWithActions;
+
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.ui.ConsoleView;
+import org.jetbrains.annotations.Nullable;
+
+// TODO: Move to the same package as ConsoleView
+/**
+ * Console that knows how to run process. Such console stores somewhere {@link ProcessHandler} passed
+ * to {@link #attachToProcess(ProcessHandler)} and may return it via {@link #getProcessHandler()}
+ *
+ * @author Ilya.Kazakevich
+ */
+public interface ConsoleWithProcess extends ConsoleView {
+  /**
+   * @return process handler of process currently running or null if no such process
+   */
+  @Nullable
+  ProcessHandler getProcessHandler();
+}
diff --git a/python/src/com/jetbrains/toolWindowWithActions/PanelWithActions.java b/python/src/com/jetbrains/toolWindowWithActions/PanelWithActions.java
new file mode 100644 (file)
index 0000000..0e6dd48
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2000-2015 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.toolWindowWithActions;
+
+import com.intellij.execution.runners.AbstractConsoleRunnerWithHistory;
+import com.intellij.ide.actions.CloseAction;
+import com.intellij.openapi.actionSystem.*;
+import com.jetbrains.python.PyBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Panel with action buttons that wraps come widget adding action buttons.
+ * Entry point is {@link #wrap(JComponent, Collection, JComponent, AnAction...)}.
+ *
+ * @author Ilya.Kazakevich
+ */
+@SuppressWarnings({"DeserializableClassInSecureContext", "SerializableClassInSecureContext"}) // Who will serialize panel?
+final class PanelWithActions extends JPanel {
+  private PanelWithActions() {
+
+  }
+
+  /**
+   * Wraps component with panel with buttons returning composite component to add somewhere.
+   *
+   * @param dataComponent           component to wrap with action panel
+   * @param closeListeners          Listeners to delegate "close all" command (when user clicks red cross aka "close" button)
+   * @param actionListenerComponent component to bind to action shortcuts (null if no shortcuts will be used)
+   * @param customActions           additional actions to add
+   * @return composite component with console on the right part and buttons on the left part
+   */
+  @NotNull
+  static JComponent wrap(@NotNull final JComponent dataComponent,
+                         @NotNull final Collection<Runnable> closeListeners,
+                         @Nullable final JComponent actionListenerComponent,
+                         @NotNull final AnAction... customActions) {
+    final PanelWithActions instance = new PanelWithActions();
+
+    // Box layout: panel goes to the left, console to the right
+    final LayoutManager layout = new BoxLayout(instance, BoxLayout.LINE_AXIS);
+    instance.setLayout(layout);
+
+    // use actions from console itself
+
+
+    final List<AnAction> actionList = new ArrayList<AnAction>(Arrays.asList(customActions));
+    final DefaultActionGroup toolbarActions = new DefaultActionGroup();
+    actionList.add(new MyCloseAction(closeListeners));
+    toolbarActions.addAll(actionList);
+
+    final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, toolbarActions, false);
+    toolbar.setTargetComponent(dataComponent);
+
+    // TODO: Move GUI and alignment out of here.
+    final JComponent toolbarComponent = toolbar.getComponent();
+
+    toolbarComponent.setMaximumSize(toolbarComponent.getPreferredSize()); // To make actions panel as small as possible (not 50% of width)
+    toolbarComponent.setAlignmentY(0);  // Align actions to the top
+    instance.add(toolbarComponent);
+    instance.add(dataComponent);
+    if (actionListenerComponent != null) {
+      AbstractConsoleRunnerWithHistory.registerActionShortcuts(actionList, actionListenerComponent);
+    }
+    return instance;
+  }
+
+  /**
+   * Closes console and notifies close listeners when user clicks "close"
+   */
+  private static final class MyCloseAction extends CloseAction {
+    @NotNull
+    private final Collection<Runnable> myCloseListeners = new ArrayList<Runnable>();
+
+    /**
+     * @param closeListeners engines to be called when user clicks "close"
+     */
+    MyCloseAction(@NotNull final Collection<Runnable> closeListeners) {
+      myCloseListeners.addAll(closeListeners);
+    }
+
+    @Override
+    public void update(final AnActionEvent e) {
+      super.update(e);
+      e.getPresentation().setText(PyBundle.message("windowWithActions.closeWindow"));
+    }
+
+    @Override
+    public void actionPerformed(final AnActionEvent e) {
+      super.actionPerformed(e);
+      for (final Runnable closeListener : myCloseListeners) {
+        closeListener.run();
+      }
+    }
+  }
+}
similarity index 96%
rename from python/src/com/jetbrains/commandInterface/console/ToolWindowApi.java
rename to python/src/com/jetbrains/toolWindowWithActions/ToolWindowApi.java
index 8c968f8541779414c68f6f67019bd3597f8e475b..b4d4e6d82611feee50b1320dd6247a9332212cfc 100644 (file)
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.jetbrains.commandInterface.console;
+package com.jetbrains.toolWindowWithActions;
 
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.wm.ToolWindow;
@@ -40,7 +40,7 @@ final class ToolWindowApi {
   private final ToolWindowManager myToolWindowManager;
 
   /**
-   * @param project project
+   * @param project    project
    * @param windowName name to be used as id (and shown to user)
    */
   ToolWindowApi(@NotNull final Project project, @NotNull final String windowName) {
diff --git a/python/src/com/jetbrains/toolWindowWithActions/WindowWithActions.java b/python/src/com/jetbrains/toolWindowWithActions/WindowWithActions.java
new file mode 100644 (file)
index 0000000..20869d9
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2000-2015 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.toolWindowWithActions;
+
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Creates toolwindow at the bottom of the screen displaying {@link ConsoleView console} or some custom {@link JComponent} with
+ * actions on the left side.
+ * <br/>
+ * To display console consider using {@link #showConsole(ConsoleView, JComponent, String, Project, Runnable, AnAction...)}.
+ * For everything else use {@link #show(JComponent, JComponent, String, Project, Runnable, AnAction...)}
+ *
+ * @author Ilya.Kazakevich
+ */
+public final class WindowWithActions {
+
+  private WindowWithActions() {
+  }
+
+
+  /**
+   * Displays console with toolwindow with "close" and "stop" actions.
+   *
+   * @param consoleWithProcess             console to display
+   * @param actionListenerComponent component to bind to actions shortcuts (can be null)
+   * @param title                   window title (should be unique!)
+   * @param project                 project where displaying takes place
+   * @param closeListeners          engines to listen for "close" events. Something that stops console process may be good example of it.
+   *                                Null if you do not want this delegate to be called.
+   * @param customActions           additional actions to add
+   */
+  public static void showConsoleWithProcess(@NotNull final ConsoleWithProcess consoleWithProcess,
+                                            @Nullable final JComponent actionListenerComponent,
+                                            @NotNull final String title,
+                                            @NotNull final Project project,
+                                            @Nullable final Collection<Runnable> closeListeners,
+                                            @NotNull final AnAction... customActions) {
+    final ConsoleStopProcessAction stopProcessAction = new ConsoleStopProcessAction(consoleWithProcess);
+
+    // Add "stop action" as action and as close listener to stop process when console is closing
+    final Collection<Runnable> resultCloseListeners = new ArrayList<Runnable>(Collections.singleton(stopProcessAction));
+    if (closeListeners != null) {
+      resultCloseListeners.addAll(closeListeners);
+    }
+    final AnAction[] resultActions = ArrayUtil.mergeArrays(new AnAction[]{stopProcessAction}, customActions);
+    showConsole(consoleWithProcess, actionListenerComponent, title, project, resultCloseListeners, resultActions);
+  }
+
+  /**
+   * Displays console in the toolwindow
+   *
+   * @param consoleView             console to display
+   * @param actionListenerComponent component to bind to actions shortcuts (can be null)
+   * @param title                   window title (should be unique!)
+   * @param project                 project where displaying takes place
+   * @param closeListeners          engine to listen for "close" events. Something that stops console process may be good example of it.
+   *                                Null if you do not want this delegate to be called.
+   * @param customActions           additional actions to add
+   */
+  public static void showConsole(@NotNull final ConsoleView consoleView,
+                                 @Nullable final JComponent actionListenerComponent,
+                                 @NotNull final String title,
+                                 @NotNull final Project project,
+                                 @Nullable final Collection<Runnable> closeListeners,
+                                 @NotNull final AnAction... customActions) {
+    final AnAction[] actions = ArrayUtil.mergeArrays(customActions, consoleView.createConsoleActions());
+    show(consoleView.getComponent(), actionListenerComponent, title, project, closeListeners, actions);
+  }
+
+  /**
+   * Displays some component in the toolwindow
+   *
+   * @param dataComponent           component to display
+   * @param actionListenerComponent component to bind to actions shortcuts (can be null)
+   * @param title                   window title (should be unique!)
+   * @param project                 project where displaying takes place
+   * @param closeListeners          engines to listen for "close" events. Something that stops console process may be good example of it.
+   *                                Null if you do not want this delegate to be called.
+   * @param customActions           additional actions to add
+   */
+  public static void show(@NotNull final JComponent dataComponent,
+                          @Nullable final JComponent actionListenerComponent,
+                          @NotNull final String title,
+                          @NotNull final Project project,
+                          @Nullable final Collection<Runnable> closeListeners,
+                          @NotNull final AnAction... customActions) {
+    final ToolWindowApi api = new ToolWindowApi(project, title);
+
+    final Collection<Runnable> closeListenersToAdd = new ArrayList<Runnable>(Collections.singleton(new MyToolWindowCloser(api)));
+    if (closeListeners != null) {
+      closeListenersToAdd.addAll(closeListeners);
+    }
+    api.add(PanelWithActions.wrap(dataComponent, closeListenersToAdd, actionListenerComponent, customActions));
+  }
+
+  /**
+   * When user clicks "close", we should close whole window, so we delegate it to {@link ToolWindowApi}
+   */
+  private static final class MyToolWindowCloser implements Runnable {
+    @NotNull
+    private final ToolWindowApi myApi;
+
+    private MyToolWindowCloser(@NotNull final ToolWindowApi api) {
+      myApi = api;
+    }
+
+    @Override
+    public void run() {
+      myApi.close();
+    }
+  }
+}
diff --git a/python/src/com/jetbrains/toolWindowWithActions/package-info.java b/python/src/com/jetbrains/toolWindowWithActions/package-info.java
new file mode 100644 (file)
index 0000000..72b08b9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2015 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 to display toolwindow on the bottom of the screen with custom content and several actions.
+ * This package also has shortcut to display {@link com.intellij.execution.ui.ConsoleView} with its actions.
+ * And when console is {@link com.jetbrains.toolWindowWithActions.ConsoleWithProcess} it also displays "stop" action
+ *
+ * Entry point is {@link com.jetbrains.toolWindowWithActions.WindowWithActions}
+ *
+ * @see com.jetbrains.toolWindowWithActions.WindowWithActions
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.toolWindowWithActions;
\ No newline at end of file