ParametersListTable () { return new ParametersListTable() { @Override public ParameterTableModelItemBase<ParameterInfoImpl> getRowItem(int row) { return super.getRowItem(row); } private final EditorTextFieldJBTableRowRenderer myRowRenderer = new EditorTextFieldJBTableRowRenderer(getProject(), JavaChangeSignatureDialog.this.getFileType().getLanguage(), myDisposable) { @Override protected String getText(JTable table, int row) { ParameterTableModelItemBase<ParameterInfoImpl> item = getRowItem(row); final String typeText = item.typeCodeFragment.getText(); final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1); String text = typeText + separator + item.parameter.getName(); final String defaultValue = item.defaultValueCodeFragment.getText(); String tail = ""; if (StringUtil.isNotEmpty(defaultValue)) { tail += " " + RefactoringBundle.message("changeSignature.default.value.label") + " " + defaultValue; } if (item.parameter.isUseAnySingleVariable()) { if (StringUtil.isNotEmpty(defaultValue)) { tail += ";"; } tail += " " + JavaRefactoringBundle.message("changeSignature.use.any.var"); } if (!StringUtil.isEmpty(tail)) { text += " //" + tail; } return " " + text; } }; @Override protected JBTableRowRenderer getRowRenderer(int row) { return myRowRenderer; } @NotNull @Override protected JBTableRowEditor getRowEditor(final ParameterTableModelItemBase<ParameterInfoImpl> item) { return new JBTableRowEditor() { private EditorTextField myTypeEditor; private EditorTextField myNameEditor; private EditorTextField myDefaultValueEditor; private JCheckBox myAnyVar; @Override public void prepareEditor(JTable table, int row) { setLayout(new BorderLayout()); final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment); myTypeEditor = new EditorTextField(document, getProject(), getFileType()); myTypeEditor.addDocumentListener(getSignatureUpdater()); myTypeEditor.setPreferredWidth(getTable().getWidth() / 2); myTypeEditor.addDocumentListener(new RowEditorChangeListener(0)); myTypeEditor.setFont(EditorUtil.getEditorFont()); add(createLabeledPanel(RefactoringBundle.message("column.name.type"), myTypeEditor), BorderLayout.WEST); myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType()); myNameEditor.addDocumentListener(getSignatureUpdater()); myNameEditor.addDocumentListener(new RowEditorChangeListener(1)); myNameEditor.setFont(EditorUtil.getEditorFont()); add(createLabeledPanel(RefactoringBundle.message("column.name.name"), myNameEditor), BorderLayout.CENTER); new TextFieldCompletionProvider() { @Override protected void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, @NotNull CompletionResultSet result) { final PsiCodeFragment fragment = item.typeCodeFragment; if (fragment instanceof PsiTypeCodeFragment) { final PsiType type; try { type = ((PsiTypeCodeFragment)fragment).getType(); } catch (Exception e) { return; } final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject) .suggestVariableName(VariableKind.PARAMETER, null, null, type); for (String completionVariant : info.names) { final LookupElementBuilder element = LookupElementBuilder.create(completionVariant); result.addElement(element.withLookupString(StringUtil.toLowerCase(completionVariant))); } } } }.apply(myNameEditor, item.parameter.getName()); if (!item.isEllipsisType() && item.parameter.isNew()) { final JPanel additionalPanel = new JPanel(new BorderLayout()); final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment); myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType()); ((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item)); myDefaultValueEditor.setPreferredWidth(getTable().getWidth() / 2); myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2)); myDefaultValueEditor.setFont(EditorUtil.getEditorFont()); String message = RefactoringBundle.message("changeSignature.default.value.label"); additionalPanel.add(createLabeledPanel(message, myDefaultValueEditor), BorderLayout.WEST); if (!isGenerateDelegate()) { myAnyVar = new JCheckBox(JavaRefactoringBundle.message("change.signature.use.any.checkbox"), item.parameter.isUseAnySingleVariable()); UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myAnyVar); DialogUtil.registerMnemonic(myAnyVar, '&'); myAnyVar.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { item.parameter.setUseAnySingleVariable(myAnyVar.isSelected()); } }); additionalPanel.add(createLabeledPanel(" "/* for correct vertical alignment */, myAnyVar), BorderLayout.CENTER); } add(additionalPanel, BorderLayout.SOUTH); } } @Override public JBTableRow getValue() { return new JBTableRow() { @Override public Object getValueAt(int column) { return switch (column) { case 0 -> item.typeCodeFragment; case 1 -> myNameEditor.getText().trim(); case 2 -> item.defaultValueCodeFragment; case 3 -> myAnyVar != null && myAnyVar.isSelected(); default -> null; }; } }; } @Override public JComponent getPreferredFocusedComponent() { final MouseEvent me = getMouseEvent(); if (me == null) { return myTypeEditor.getFocusTarget(); } final double x = me.getPoint().getX(); return x <= getTypesColumnWidth() ? myTypeEditor.getFocusTarget() : myDefaultValueEditor == null || x <= getNamesColumnWidth() ? myNameEditor.getFocusTarget() : myDefaultValueEditor.getFocusTarget(); } @Override public JComponent[] getFocusableComponents() { final List<JComponent> focusable = new ArrayList<>(); focusable.add(myTypeEditor.getFocusTarget()); focusable.add(myNameEditor.getFocusTarget()); if (myDefaultValueEditor != null) { focusable.add(myDefaultValueEditor.getFocusTarget()); } if (myAnyVar != null) { focusable.add(myAnyVar); } return focusable.toArray(new JComponent[0]); } }; } @Override protected boolean isRowEmpty(int row) { ParameterInfoImpl parameter = getRowItem(row).parameter; return StringUtil.isEmpty(parameter.getName()) && StringUtil.isEmpty(parameter.getTypeText()); } }; }