call `SearchEverywhereContributor#getElementsRenderer` once and cache the result
[idea/community.git] / platform / lang-impl / src / com / intellij / ide / actions / searcheverywhere / GroupedListFactory.java
1 // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.ide.actions.searcheverywhere;
3
4 import com.intellij.ide.actions.SearchEverywhereClassifier;
5 import com.intellij.ide.util.gotoByName.GotoActionModel;
6 import com.intellij.ui.AppUIUtil;
7 import com.intellij.ui.CellRendererPanel;
8 import com.intellij.ui.SeparatorComponent;
9 import com.intellij.ui.SimpleColoredComponent;
10 import com.intellij.ui.components.JBList;
11 import com.intellij.util.ui.JBUI;
12 import com.intellij.util.ui.UIUtil;
13 import org.jetbrains.annotations.Nls;
14
15 import javax.swing.*;
16 import javax.swing.border.Border;
17 import java.awt.*;
18
19 class GroupedListFactory extends SEResultsListFactory {
20   @Override
21   public SearchListModel createModel() {
22     return new GroupedSearchListModel();
23   }
24
25   @Override
26   public JBList<Object> createList(SearchListModel model) {
27     return new JBList<>(model);
28   }
29
30   @Override
31   ListCellRenderer<Object> createListRenderer(SearchListModel model, SearchEverywhereHeader header) {
32     GroupedSearchListModel groupedModel = (GroupedSearchListModel)model;
33     return new ListCellRenderer<>() {
34
35       @Override
36       public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
37         if (value == SearchListModel.MORE_ELEMENT) {
38           Component component = myMoreRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
39           component.setPreferredSize(UIUtil.updateListRowHeight(component.getPreferredSize()));
40           return component;
41         }
42
43         SearchEverywhereContributor<Object> contributor = groupedModel.getContributorForIndex(index);
44         Component component = SearchEverywhereClassifier.EP_Manager.getListCellRendererComponent(
45           list, value, index, isSelected, cellHasFocus);
46         if (component == null) {
47           ListCellRenderer<? super Object> renderer = groupedModel.getRendererForIndex(index);
48           //noinspection ConstantConditions
49           component = renderer.getListCellRendererComponent(list, value, index, isSelected, true);
50         }
51
52         if (component instanceof JComponent) {
53           Border border = ((JComponent)component).getBorder();
54           if (border != GotoActionModel.GotoActionListCellRenderer.TOGGLE_BUTTON_BORDER) {
55             ((JComponent)component).setBorder(JBUI.Borders.empty(1, 2));
56           }
57         }
58         AppUIUtil.targetToDevice(component, list);
59         component.setPreferredSize(UIUtil.updateListRowHeight(component.getPreferredSize()));
60         if (!header.getSelectedTab().isSingleContributor() && groupedModel.isGroupFirstItem(index)) {
61           //noinspection ConstantConditions
62           component = myGroupTitleRenderer.withDisplayedData(contributor.getFullGroupName(), component);
63         }
64
65         return component;
66       }
67     };
68   }
69
70   private final GroupTitleRenderer myGroupTitleRenderer = new GroupTitleRenderer();
71
72   private static class GroupTitleRenderer extends CellRendererPanel {
73
74     final SimpleColoredComponent titleLabel = new SimpleColoredComponent();
75
76     GroupTitleRenderer() {
77       setLayout(new BorderLayout());
78       SeparatorComponent separatorComponent = new SeparatorComponent(
79         titleLabel.getPreferredSize().height / 2, JBUI.CurrentTheme.BigPopup.listSeparatorColor(), null);
80
81       JPanel topPanel = JBUI.Panels.simplePanel(5, 0)
82         .addToCenter(separatorComponent)
83         .addToLeft(titleLabel)
84         .withBorder(JBUI.Borders.empty(1, 7))
85         .withBackground(UIUtil.getListBackground());
86       add(topPanel, BorderLayout.NORTH);
87     }
88
89     public GroupTitleRenderer withDisplayedData(@Nls String title, Component itemContent) {
90       titleLabel.clear();
91       titleLabel.append(title, SMALL_LABEL_ATTRS);
92       Component prevContent = ((BorderLayout)getLayout()).getLayoutComponent(BorderLayout.CENTER);
93       if (prevContent != null) {
94         remove(prevContent);
95       }
96       add(itemContent, BorderLayout.CENTER);
97       accessibleContext = itemContent.getAccessibleContext();
98
99       return this;
100     }
101   }
102 }