SearchResultPanel (@NotNull Consumer<? super PluginsGroupComponent> selectionListener) { SearchUpDownPopupController installedController = new SearchUpDownPopupController(mySearchTextField) { @Override protected @NotNull @NonNls List<String> getAttributes() { return Arrays .asList( "/downloaded", "/outdated", "/enabled", "/disabled", "/invalid", "/bundled", SearchWords.VENDOR.getValue(), SearchWords.TAG.getValue() ); } @Override protected @Nullable SortedSet<String> getValues(@NotNull String attribute) { return SearchWords.VENDOR.getValue().equals(attribute) ? myPluginModel.getVendors() : SearchWords.TAG.getValue().equals(attribute) ? myPluginModel.getTags() : null; } @Override protected void showPopupForQuery() { showSearchPanel(mySearchTextField.getText()); } }; MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler(); installedController.setSearchResultEventHandler(eventHandler); PluginsGroupComponent panel = new PluginsGroupComponent(eventHandler) { @Override protected @NotNull ListPluginComponent createListComponent(@NotNull IdeaPluginDescriptor descriptor, @NotNull PluginsGroup group) { return new ListPluginComponent(myPluginModel, descriptor, group, mySearchListener, false); } }; panel.setSelectionListener(selectionListener); registerCopyProvider(panel); myInstalledSearchCallback = updateAction -> { List<String> queries = new ArrayList<>(); new SearchQueryParser.Installed(mySearchTextField.getText()) { @Override protected void addToSearchQuery(@NotNull String query) { queries.add(query); } @Override protected void handleAttribute(@NotNull String name, @NotNull String value) { if (!updateAction.myState) { queries.add(name + (value.isEmpty() ? "" : SearchQueryParser.wrapAttribute(value))); } } }; if (updateAction.myState) { for (AnAction action : myInstalledSearchGroup.getChildren(null)) { if (action != updateAction) { ((InstalledSearchOptionAction)action).myState = false; } } queries.add(updateAction.getQuery()); } else { queries.remove(updateAction.getQuery()); } try { myInstalledSearchSetState = false; String query = StringUtil.join(queries, " "); mySearchTextField.setTextIgnoreEvents(query); if (query.isEmpty()) { myInstalledTab.hideSearchPanel(); } else { myInstalledTab.showSearchPanel(query); } } finally { myInstalledSearchSetState = true; } }; myInstalledSearchPanel = new SearchResultPanel(installedController, panel, false, 0, 0) { @Override protected void setEmptyText(@NotNull String query) { myPanel.getEmptyText().setText(IdeBundle.message("plugins.configurable.nothing.found")); if (query.contains("/downloaded") || query.contains("/outdated") || query.contains("/enabled") || query.contains("/disabled") || query.contains("/invalid") || query.contains("/bundled")) { return; } myPanel.getEmptyText().appendSecondaryText(IdeBundle.message("plugins.configurable.search.in.marketplace"), SimpleTextAttributes.LINK_PLAIN_ATTRIBUTES, e -> myTabHeaderComponent.setSelectionWithEvents(MARKETPLACE_TAB)); } @Override protected void handleQuery(@NotNull String query, @NotNull PluginsGroup result) { myPluginModel.setInvalidFixCallback(null); SearchQueryParser.Installed parser = new SearchQueryParser.Installed(query); if (myInstalledSearchSetState) { for (AnAction action : myInstalledSearchGroup.getChildren(null)) { ((InstalledSearchOptionAction)action).setState(parser); } } List<IdeaPluginDescriptor> descriptors = myPluginModel.getInstalledDescriptors(); if (!parser.vendors.isEmpty()) { for (Iterator<IdeaPluginDescriptor> I = descriptors.iterator(); I.hasNext(); ) { if (!MyPluginModel.isVendor(I.next(), parser.vendors)) { I.remove(); } } } if (!parser.tags.isEmpty()) { for (Iterator<IdeaPluginDescriptor> I = descriptors.iterator(); I.hasNext(); ) { if (!ContainerUtil.intersects(getTags(I.next()), parser.tags)) { I.remove(); } } } for (Iterator<IdeaPluginDescriptor> I = descriptors.iterator(); I.hasNext(); ) { IdeaPluginDescriptor descriptor = I.next(); if (parser.attributes) { if (parser.enabled && (!myPluginModel.isEnabled(descriptor) || myPluginModel.hasErrors(descriptor))) { I.remove(); continue; } if (parser.disabled && (myPluginModel.isEnabled(descriptor) || myPluginModel.hasErrors(descriptor))) { I.remove(); continue; } if (parser.bundled && !descriptor.isBundled()) { I.remove(); continue; } if (parser.downloaded && descriptor.isBundled()) { I.remove(); continue; } if (parser.invalid && !myPluginModel.hasErrors(descriptor)) { I.remove(); continue; } if (parser.needUpdate && !PluginUpdatesService.isNeedUpdate(descriptor)) { I.remove(); continue; } } if (parser.searchQuery != null && !containsQuery(descriptor, parser.searchQuery)) { I.remove(); } } result.descriptors.addAll(descriptors); PluginManagerUsageCollector.performInstalledTabSearch(ProjectUtil.getActiveProject(), parser, result.descriptors); if (!result.descriptors.isEmpty()) { if (parser.invalid) { myPluginModel.setInvalidFixCallback(() -> { PluginsGroup group = myInstalledSearchPanel.getGroup(); if (group.ui == null) { myPluginModel.setInvalidFixCallback(null); return; } PluginsGroupComponent resultPanel = myInstalledSearchPanel.getPanel(); for (IdeaPluginDescriptor descriptor : new ArrayList<>(group.descriptors)) { if (!myPluginModel.hasErrors(descriptor)) { resultPanel.removeFromGroup(group, descriptor); } } group.titleWithCount(); myInstalledSearchPanel.fullRepaint(); if (group.descriptors.isEmpty()) { myPluginModel.setInvalidFixCallback(null); myInstalledSearchPanel.removeGroup(); } }); } else if (parser.needUpdate) { result.rightAction = new LinkLabelButton<>(IdeBundle.message("plugin.manager.update.all"), null, (__, ___) -> { result.rightAction.setEnabled(false); for (ListPluginComponent plugin : result.ui.plugins) { plugin.updatePlugin(); } }); } Collection<IdeaPluginDescriptor> updates = PluginUpdatesService.getUpdates(); if (!ContainerUtil.isEmpty(updates)) { myPostFillGroupCallback = () -> { applyUpdates(myPanel, updates); selectionListener.accept(myInstalledPanel); }; } } } }; return myInstalledSearchPanel; }