void (@NotNull List<T> options, @NotNull CallBack<T> callBack) { final DefaultListModel<T> model = new DefaultListModel<>(); int maxOffset = -1; for (final T option : options) { model.addElement(option); maxOffset = Math.max(maxOffset, option.rangeStream().mapToInt(TextRange::getEndOffset).max().orElse(-1)); } final JBList<T> list = new JBList<>(model); list.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //noinspection unchecked setText(((T)value).getText()); return this; } }); list.addListSelectionListener(e -> { final T selectedValue = list.getSelectedValue(); if (selectedValue == null) return; dropHighlighters(); selectedValue.rangeStream().forEach(x -> { final RangeHighlighter highlighter = myEditor.getMarkupModel() .addRangeHighlighter(x.getStartOffset(), x.getEndOffset(), HIGHLIGHT_LAYER, myAttributes, HighlighterTargetArea.EXACT_RANGE); myRangeHighlighters.add(highlighter); }); }); final JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(list) .setTitle(StreamDebuggerBundle.message("multiple.chains.popup.title")) .setMovable(true) .setResizable(false) .setRequestFocus(true) .setItemChosenCallback(() -> callBack.chosen(list.getSelectedValue())) .addListener(new JBPopupListener() { @Override public void onClosed(@NotNull LightweightWindowEvent event) { dropHighlighters(); } }) .createPopup(); if (maxOffset != -1) { myEditor.getCaretModel().moveToOffset(maxOffset); } popup.showInBestPositionFor(myEditor); }