private static JBPopup getPsiElementPopup( final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap, final String title, final Processor<Object> processor) { final Ref<Boolean> hasMnemonic = Ref.create(false); final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() { { setFocusBorderEnabled(false); } @Override public String getElementText(PsiElement element) { String customName = itemsMap.get(element).getCustomName(); return (customName != null ? customName : super.getElementText(element)); } @Override protected Icon getIcon(PsiElement element) { Icon customIcon = itemsMap.get(element).getCustomIcon(); return customIcon != null ? customIcon : super.getIcon(element); } @Override public String getContainerText(PsiElement element, String name) { PsiFile file = element.getContainingFile(); return file != null && !getElementText(element).equals(file.getName()) ? "(" + file.getName() + ")" : null; } @Override protected DefaultListCellRenderer getRightCellRenderer() { return null; } @Override protected boolean customizeNonPsiElementLeftRenderer( ColoredListCellRenderer renderer, JList list, Object value, int index, boolean selected, boolean hasFocus) { final GotoRelatedItem item = (GotoRelatedItem) value; Color color = list.getForeground(); final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color); final String name = item.getCustomName(); if (name == null) return false; renderer.append(name, nameAttributes); renderer.setIcon(item.getCustomIcon()); return true; } @Override public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final JPanel component = (JPanel) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (!hasMnemonic.get()) return component; final JPanel panelWithMnemonic = new JPanel(new BorderLayout()); final int mnemonic = getMnemonic(value, itemsMap); final JLabel label = new JLabel(""); if (mnemonic != -1) { label.setText(mnemonic + "."); label.setDisplayedMnemonicIndex(0); } label.setPreferredSize(new JLabel("8.").getPreferredSize()); final JComponent leftRenderer = (JComponent) component.getComponents()[0]; component.remove(leftRenderer); panelWithMnemonic.setBackground(leftRenderer.getBackground()); label.setBackground(leftRenderer.getBackground()); panelWithMnemonic.add(label, BorderLayout.WEST); panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER); component.add(panelWithMnemonic); return component; } }; final ListPopupImpl popup = new ListPopupImpl( new BaseListPopupStep<Object>(title, Arrays.asList(elements)) { @Override public boolean isSpeedSearchEnabled() { return true; } @Override public PopupStep onChosen(Object selectedValue, boolean finalChoice) { processor.process(selectedValue); return super.onChosen(selectedValue, finalChoice); } }) { @Override protected ListCellRenderer getListElementRenderer() { return renderer; } }; popup.setMinimumSize(new Dimension(200, -1)); for (Object item : elements) { final int mnemonic = getMnemonic(item, itemsMap); if (mnemonic != -1) { final Action action = createNumberAction(mnemonic, popup, itemsMap, processor); popup.registerAction( mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action); hasMnemonic.set(true); } } return popup; }
private static JBPopup getPsiElementPopup( final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap, final String title, final boolean showContainingModules, final Processor<Object> processor) { final Ref<Boolean> hasMnemonic = Ref.create(false); final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() { { setFocusBorderEnabled(false); } @Override public String getElementText(PsiElement element) { String customName = itemsMap.get(element).getCustomName(); return (customName != null ? customName : super.getElementText(element)); } @Override protected Icon getIcon(PsiElement element) { Icon customIcon = itemsMap.get(element).getCustomIcon(); return customIcon != null ? customIcon : super.getIcon(element); } @Override public String getContainerText(PsiElement element, String name) { String customContainerName = itemsMap.get(element).getCustomContainerName(); if (customContainerName != null) { return customContainerName; } PsiFile file = element.getContainingFile(); return file != null && !getElementText(element).equals(file.getName()) ? "(" + file.getName() + ")" : null; } @Override protected DefaultListCellRenderer getRightCellRenderer(Object value) { return showContainingModules ? super.getRightCellRenderer(value) : null; } @Override protected boolean customizeNonPsiElementLeftRenderer( ColoredListCellRenderer renderer, JList list, Object value, int index, boolean selected, boolean hasFocus) { final GotoRelatedItem item = (GotoRelatedItem) value; Color color = list.getForeground(); final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, color); final String name = item.getCustomName(); if (name == null) return false; renderer.append(name, nameAttributes); renderer.setIcon(item.getCustomIcon()); return true; } @Override public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final JPanel component = (JPanel) super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (!hasMnemonic.get()) return component; final JPanel panelWithMnemonic = new JPanel(new BorderLayout()); final int mnemonic = getMnemonic(value, itemsMap); final JLabel label = new JLabel(""); if (mnemonic != -1) { label.setText(mnemonic + "."); label.setDisplayedMnemonicIndex(0); } label.setPreferredSize(new JLabel("8.").getPreferredSize()); final JComponent leftRenderer = (JComponent) component.getComponents()[0]; component.remove(leftRenderer); panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0)); panelWithMnemonic.setBackground(leftRenderer.getBackground()); label.setBackground(leftRenderer.getBackground()); panelWithMnemonic.add(label, BorderLayout.WEST); panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER); component.add(panelWithMnemonic); return component; } }; final ListPopupImpl popup = new ListPopupImpl( new BaseListPopupStep<Object>(title, Arrays.asList(elements)) { @Override public boolean isSpeedSearchEnabled() { return true; } @Override public String getIndexedString(Object value) { if (value instanceof GotoRelatedItem) { //noinspection ConstantConditions return ((GotoRelatedItem) value).getCustomName(); } PsiElement element = (PsiElement) value; if (!element.isValid()) return "INVALID"; return renderer.getElementText(element) + " " + renderer.getContainerText(element, null); } @Override public PopupStep onChosen(Object selectedValue, boolean finalChoice) { processor.process(selectedValue); return super.onChosen(selectedValue, finalChoice); } }) {}; popup .getList() .setCellRenderer( new PopupListElementRenderer(popup) { Map<Object, String> separators = new HashMap<Object, String>(); { final ListModel model = popup.getList().getModel(); String current = null; boolean hasTitle = false; for (int i = 0; i < model.getSize(); i++) { final Object element = model.getElementAt(i); final GotoRelatedItem item = itemsMap.get(element); if (item != null && !StringUtil.equals(current, item.getGroup())) { current = item.getGroup(); separators.put(element, current); if (!hasTitle && !StringUtil.isEmpty(current)) { hasTitle = true; } } } if (!hasTitle) { separators.remove(model.getElementAt(0)); } } @Override public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final Component component = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); final String separator = separators.get(value); if (separator != null) { JPanel panel = new JPanel(new BorderLayout()); panel.add(component, BorderLayout.CENTER); final SeparatorWithText sep = new SeparatorWithText() { @Override protected void paintComponent(Graphics g) { g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor())); g.fillRect(0, 0, getWidth(), getHeight()); super.paintComponent(g); } }; sep.setCaption(separator); panel.add(sep, BorderLayout.NORTH); return panel; } return component; } }); popup.setMinimumSize(new Dimension(200, -1)); for (Object item : elements) { final int mnemonic = getMnemonic(item, itemsMap); if (mnemonic != -1) { final Action action = createNumberAction(mnemonic, popup, itemsMap, processor); popup.registerAction( mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action); popup.registerAction( mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action); hasMnemonic.set(true); } } return popup; }