public void addRunContentListener(final RunContentListener listener, final Executor executor) {
    final Disposable disposable = Disposer.newDisposable();
    myProject
        .getMessageBus()
        .connect(disposable)
        .subscribe(
            RUN_CONTENT_TOPIC,
            new RunContentWithExecutorListener() {
              @Override
              public void contentSelected(
                  RunContentDescriptor descriptor, @NotNull Executor executor2) {
                if (executor2.equals(executor)) {
                  listener.contentSelected(descriptor);
                }
              }

              @Override
              public void contentRemoved(
                  RunContentDescriptor descriptor, @NotNull Executor executor2) {
                if (executor2.equals(executor)) {
                  listener.contentRemoved(descriptor);
                }
              }
            });
    myListeners.put(listener, disposable);
  }
  @Nullable
  public RunContentDescriptor getSelectedContent() {
    for (String activeWindow : myToolwindowIdZbuffer) {
      final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(activeWindow);
      if (contentManager == null) {
        continue;
      }

      final Content selectedContent = contentManager.getSelectedContent();
      if (selectedContent == null) {
        if (contentManager.getContentCount() == 0) {
          // continue to the next window if the content manager is empty
          continue;
        } else {
          // stop iteration over windows because there is some content in the window and the window
          // is the last used one
          break;
        }
      }
      // here we have selected content
      return getRunContentDescriptorByContent(selectedContent);
    }

    return null;
  }
 private ContentManager getContentManagerForRunner(final Executor executor) {
   final ContentManager contentManager =
       myToolwindowIdToContentManagerMap.get(executor.getToolWindowId());
   if (contentManager == null) {
     LOG.error("Runner " + executor.getId() + " is not registered");
   }
   return contentManager;
 }
  private void registerToolwindow(@NotNull final Executor executor) {
    final String toolWindowId = executor.getToolWindowId();
    final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
    if (toolWindowManager == null) return; // headless environment
    if (toolWindowManager.getToolWindow(toolWindowId) != null) {
      return;
    }

    final ToolWindow toolWindow =
        toolWindowManager.registerToolWindow(
            toolWindowId, true, ToolWindowAnchor.BOTTOM, this, true);

    final ContentManager contentManager = toolWindow.getContentManager();
    class MyDataProvider implements DataProvider {
      private int myInsideGetData = 0;

      public Object getData(String dataId) {
        myInsideGetData++;
        try {
          if (PlatformDataKeys.HELP_ID.is(dataId)) {
            return executor.getHelpId();
          } else {
            return myInsideGetData == 1
                ? DataManager.getInstance()
                    .getDataContext(contentManager.getComponent())
                    .getData(dataId)
                : null;
          }
        } finally {
          myInsideGetData--;
        }
      }
    }
    contentManager.addDataProvider(new MyDataProvider());

    toolWindow.setIcon(executor.getToolWindowIcon());
    new ContentManagerWatcher(toolWindow, contentManager);
    contentManager.addContentManagerListener(
        new ContentManagerAdapter() {
          public void selectionChanged(final ContentManagerEvent event) {
            final Content content = event.getContent();
            final RunContentDescriptor descriptor =
                content != null ? getRunContentDescriptorByContent(content) : null;
            getSyncPublisher().contentSelected(descriptor, executor);
          }
        });
    myToolwindowIdToContentManagerMap.put(toolWindowId, contentManager);
    Disposer.register(
        contentManager,
        new Disposable() {
          public void dispose() {
            unregisterToolwindow(toolWindowId);
          }
        });
    myToolwindowIdZbuffer.addLast(toolWindowId);
  }
  public RunContentDescriptor[] getAllDescriptors() {
    final List<RunContentDescriptor> descriptors = new ArrayList<RunContentDescriptor>();
    final String[] ids =
        myToolwindowIdToContentManagerMap
            .keySet()
            .toArray(new String[myToolwindowIdToContentManagerMap.size()]);
    for (String id : ids) {
      final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(id);
      final Content[] contents = contentManager.getContents();
      for (final Content content : contents) {
        final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
        if (descriptor != null) {
          descriptors.add(descriptor);
        }
      }
    }

    return descriptors.toArray(new RunContentDescriptor[descriptors.size()]);
  }
 @Override
 @Nullable
 public ToolWindow getToolWindowByDescriptor(@NotNull final RunContentDescriptor descriptor) {
   for (Map.Entry<String, ContentManager> entry : myToolwindowIdToContentManagerMap.entrySet()) {
     if (getRunContentByDescriptor(entry.getValue(), descriptor) != null) {
       return ToolWindowManager.getInstance(myProject).getToolWindow(entry.getKey());
     }
   }
   return null;
 }
  @NotNull
  public List<RunContentDescriptor> getAllDescriptors() {
    if (myToolwindowIdToContentManagerMap.isEmpty()) {
      return Collections.emptyList();
    }
    final String[] ids =
        myToolwindowIdToContentManagerMap
            .keySet()
            .toArray(new String[myToolwindowIdToContentManagerMap.size()]);
    final List<RunContentDescriptor> descriptors = new ArrayList<RunContentDescriptor>();
    for (String id : ids) {
      final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(id);
      for (final Content content : contentManager.getContents()) {
        final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
        if (descriptor != null) {
          descriptors.add(descriptor);
        }
      }
    }

    return descriptors;
  }
  @Nullable
  public RunContentDescriptor getSelectedContent() {
    final String activeWindow =
        myToolwindowIdZbuffer.isEmpty() ? null : myToolwindowIdZbuffer.getFirst();

    if (activeWindow != null) {
      final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(activeWindow);
      if (contentManager != null) {
        final Content selectedContent = contentManager.getSelectedContent();
        if (selectedContent != null) {
          final RunContentDescriptor runContentDescriptorByContent =
              getRunContentDescriptorByContent(selectedContent);
          if (runContentDescriptorByContent != null) {
            return runContentDescriptorByContent;
          }
        }
      }
    }
    return null;
  }
 public void removeRunContentListener(final RunContentListener listener) {
   Disposable disposable = myListeners.remove(listener);
   if (disposable != null) {
     Disposer.dispose(disposable);
   }
 }
 private void unregisterToolwindow(final String id) {
   final ContentManager manager = myToolwindowIdToContentManagerMap.get(id);
   manager.removeAllContents(true);
   myToolwindowIdToContentManagerMap.remove(id);
   myToolwindowIdZbuffer.remove(id);
 }