@Override
      protected @NotNull JComponent createPluginsPanel(@NotNull Consumer<? super PluginsGroupComponent> selectionListener) {
        MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler();
        myInstalledPanel = new PluginsGroupComponent(eventHandler) {
          @Override
          protected @NotNull ListPluginComponent createListComponent(@NotNull IdeaPluginDescriptor descriptor,
                                                                     @NotNull PluginsGroup group) {
            return new ListPluginComponent(myPluginModel, descriptor, group, mySearchListener, false);
          }
        };

        myInstalledPanel.setSelectionListener(selectionListener);
        myInstalledPanel.getAccessibleContext().setAccessibleName(IdeBundle.message("plugin.manager.installed.panel.accessible.name"));
        registerCopyProvider(myInstalledPanel);

        //noinspection ConstantConditions
        ((SearchUpDownPopupController)myInstalledSearchPanel.controller).setEventHandler(eventHandler);

        try {
          PluginLogo.startBatchMode();

          PluginsGroup installing = new PluginsGroup(IdeBundle.message("plugins.configurable.installing"), PluginsGroupType.INSTALLING);
          installing.descriptors.addAll(MyPluginModel.getInstallingPlugins());
          if (!installing.descriptors.isEmpty()) {
            installing.sortByName();
            installing.titleWithCount();
            myInstalledPanel.addGroup(installing);
          }

          PluginsGroup downloaded = new PluginsGroup(IdeBundle.message("plugins.configurable.downloaded"), PluginsGroupType.INSTALLED);
          downloaded.descriptors.addAll(InstalledPluginsState.getInstance().getInstalledPlugins());

          Map<Boolean, List<IdeaPluginDescriptorImpl>> visiblePlugins = PluginManager
            .getVisiblePlugins(RegistryManager.getInstance().is("plugins.show.implementation.details"))
            .collect(Collectors.partitioningBy(IdeaPluginDescriptorImpl::isBundled));

          List<IdeaPluginDescriptorImpl> nonBundledPlugins = visiblePlugins.get(Boolean.FALSE);
          downloaded.descriptors.addAll(nonBundledPlugins);

          LinkListener<Object> updateAllListener = new LinkListener<>() {
            @Override
            public void linkSelected(LinkLabel<Object> aSource, Object aLinkData) {
              myUpdateAll.setEnabled(false);
              myUpdateAllBundled.setEnabled(false);

              for (UIPluginGroup group : getInstalledGroups()) {
                if (group.excluded) {
                  continue;
                }
                for (ListPluginComponent plugin : group.plugins) {
                  plugin.updatePlugin();
                }
              }
            }
          };
          myUpdateAll.setListener(updateAllListener, null);
          downloaded.addRightAction(myUpdateAll);
          downloaded.addRightAction(myUpdateCounter);

          if (!downloaded.descriptors.isEmpty()) {
            downloaded.sortByName();

            long enabledNonBundledCount = nonBundledPlugins.stream()
              .map(IdeaPluginDescriptorImpl::getPluginId)
              .filter(descriptor -> !PluginManagerCore.isDisabled(descriptor))
              .count();
            downloaded.titleWithCount(Math.toIntExact(enabledNonBundledCount));
            myInstalledPanel.addGroup(downloaded);
            myPluginModel.addEnabledGroup(downloaded);
          }

          myPluginModel.setDownloadedGroup(myInstalledPanel, downloaded, installing);

          String defaultCategory = IdeBundle.message("plugins.configurable.other.bundled");
          visiblePlugins.get(Boolean.TRUE)
            .stream()
            .collect(Collectors.groupingBy(descriptor -> StringUtil.defaultIfEmpty(descriptor.getDisplayCategory(), defaultCategory)))
            .entrySet()
            .stream()
            .map(entry -> new ComparablePluginsGroup(entry.getKey(), entry.getValue()))
            .sorted((o1, o2) -> defaultCategory.equals(o1.title) ? 1 :
                                defaultCategory.equals(o2.title) ? -1 :
                                o1.compareTo(o2))
            .forEachOrdered(group -> {
              myInstalledPanel.addGroup(group);
              myPluginModel.addEnabledGroup(group);
            });

          myUpdateAllBundled.setListener(updateAllListener, null);
          myBundledUpdateGroup.addRightAction(myUpdateAllBundled);
          myBundledUpdateGroup.addRightAction(myUpdateCounterBundled);

          myPluginUpdatesService.calculateUpdates(updates -> {
            if (ContainerUtil.isEmpty(updates)) {
              clearUpdates(myInstalledPanel);
              clearUpdates(myInstalledSearchPanel.getPanel());
            }
            else {
              applyUpdates(myInstalledPanel, updates);
              applyUpdates(myInstalledSearchPanel.getPanel(), updates);
            }
            applyBundledUpdates(updates);
            selectionListener.accept(myInstalledPanel);
            selectionListener.accept(myInstalledSearchPanel.getPanel());
          });
        }
        finally {
          PluginLogo.endBatchMode();
        }

        return createScrollPane(myInstalledPanel, true);
      }
@Override
      protected @NotNull JComponent createPluginsPanel(@NotNull Consumer<? super PluginsGroupComponent> selectionListener)