/* * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.ui; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiElement; import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.ui.TitledSeparator; import com.intellij.util.containers.MultiMap; import kotlin.Unit; import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.KotlinFileType; import org.jetbrains.kotlin.idea.core.KotlinNameSuggester; import org.jetbrains.kotlin.idea.core.UtilsKt; import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtilKt; import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.IntroduceTypeAliasDescriptor; import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.IntroduceTypeAliasImplKt; import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.KotlinIntroduceTypeAliasHandler; import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.TypeParameter; import org.jetbrains.kotlin.idea.refactoring.introduce.ui.KotlinSignatureComponent; import org.jetbrains.kotlin.lexer.KtModifierKeywordToken; import org.jetbrains.kotlin.lexer.KtTokens; import javax.swing.*; import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.*; import java.util.List; public class KotlinIntroduceTypeAliasDialog extends DialogWrapper { private JPanel contentPane; private TitledSeparator inputParametersPanel; private JComboBox visibilityBox; private KotlinSignatureComponent signaturePreviewField; private JPanel aliasNamePanel; private NameSuggestionsField aliasNameField; private JLabel aliasNameLabel; private IntroduceTypeAliasParameterTablePanel parameterTablePanel; private final Project project; private final IntroduceTypeAliasDescriptor originalDescriptor; private IntroduceTypeAliasDescriptor currentDescriptor; private final Function1<KotlinIntroduceTypeAliasDialog, Unit> onAccept; public KotlinIntroduceTypeAliasDialog( @NotNull Project project, @NotNull IntroduceTypeAliasDescriptor originalDescriptor, @NotNull Function1<KotlinIntroduceTypeAliasDialog, Unit> onAccept) { super(project, true); this.project = project; this.originalDescriptor = originalDescriptor; this.currentDescriptor = originalDescriptor; this.onAccept = onAccept; setModal(true); setTitle(KotlinIntroduceTypeAliasHandler.REFACTORING_NAME); init(); update(); } private void createUIComponents() { this.signaturePreviewField = new KotlinSignatureComponent("", project); } private boolean isVisibilitySectionAvailable() { return !getApplicableVisibilities().isEmpty(); } @NotNull private List<KtModifierKeywordToken> getApplicableVisibilities() { return IntroduceTypeAliasImplKt.getApplicableVisibilities(originalDescriptor.getOriginalData()); } private String getAliasName() { return UtilsKt.quoteIfNeeded(aliasNameField.getEnteredName()); } @Nullable private KtModifierKeywordToken getVisibility() { if (!isVisibilitySectionAvailable()) return null; return (KtModifierKeywordToken) visibilityBox.getSelectedItem(); } private boolean checkNames() { if (!KotlinNameSuggester.INSTANCE.isIdentifier(getAliasName())) return false; if (parameterTablePanel != null) { for (IntroduceTypeAliasParameterTablePanel.TypeParameterInfo parameterInfo : parameterTablePanel.getSelectedTypeParameterInfos()) { if (!KotlinNameSuggester.INSTANCE.isIdentifier(parameterInfo.getName())) return false; } } return true; } private void update() { this.currentDescriptor = createDescriptor(); setOKActionEnabled(checkNames()); signaturePreviewField.setText(IntroduceTypeAliasImplKt.generateTypeAlias(currentDescriptor, true).getText()); } @Override protected void init() { super.init(); //noinspection unchecked visibilityBox.setModel(new DefaultComboBoxModel(getApplicableVisibilities().toArray())); //noinspection unchecked visibilityBox.setRenderer( new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus ) { String tokenValue = value != null ? ((KtModifierKeywordToken) value).getValue() : null; return super.getListCellRendererComponent(list, tokenValue, index, isSelected, cellHasFocus); } } ); aliasNameField = new NameSuggestionsField(new String[]{originalDescriptor.getName()}, project, KotlinFileType.INSTANCE); aliasNameField.addDataChangedListener( new NameSuggestionsField.DataChanged() { @Override public void dataChanged() { update(); } } ); aliasNamePanel.add(aliasNameField, BorderLayout.CENTER); aliasNameLabel.setLabelFor(aliasNameField); boolean enableVisibility = isVisibilitySectionAvailable(); visibilityBox.setEnabled(enableVisibility); if (enableVisibility) { KtModifierKeywordToken defaultVisibility = originalDescriptor.getVisibility(); if (defaultVisibility == null) { defaultVisibility = KtTokens.PUBLIC_KEYWORD; } visibilityBox.setSelectedItem(defaultVisibility); } visibilityBox.addItemListener( new ItemListener() { @Override public void itemStateChanged(@NotNull ItemEvent e) { update(); } } ); if (!originalDescriptor.getTypeParameters().isEmpty()) { parameterTablePanel = new IntroduceTypeAliasParameterTablePanel() { @Override protected void updateSignature() { KotlinIntroduceTypeAliasDialog.this.update(); } @Override protected void onEnterAction() { doOKAction(); } @Override protected void onCancelAction() { doCancelAction(); } }; parameterTablePanel.init(originalDescriptor.getTypeParameters()); inputParametersPanel.setText("Type &Parameters"); inputParametersPanel.setLabelFor(parameterTablePanel.getTable()); inputParametersPanel.add(parameterTablePanel); } else { inputParametersPanel.setVisible(false); } } @SuppressWarnings("SuspiciousMethodCalls") @Override protected void doOKAction() { MultiMap<PsiElement, String> conflicts = IntroduceTypeAliasImplKt.validate(currentDescriptor).getConflicts(); KotlinRefactoringUtilKt.checkConflictsInteractively( project, conflicts, new Function0<Unit>() { @Override public Unit invoke() { close(OK_EXIT_CODE); return Unit.INSTANCE; } }, new Function0<Unit>() { @Override public Unit invoke() { KotlinIntroduceTypeAliasDialog.super.doOKAction(); return onAccept.invoke(KotlinIntroduceTypeAliasDialog.this); } } ); } @Override public JComponent getPreferredFocusedComponent() { return aliasNameField; } @Override protected JComponent createCenterPanel() { return contentPane; } @NotNull @Override protected JComponent createContentPane() { return contentPane; } @NotNull private IntroduceTypeAliasDescriptor createDescriptor() { return originalDescriptor.copy( originalDescriptor.getOriginalData(), getAliasName(), getVisibility(), parameterTablePanel != null ? parameterTablePanel.getSelectedTypeParameters() : Collections.<TypeParameter>emptyList() ); } public IntroduceTypeAliasDescriptor getCurrentDescriptor() { return currentDescriptor; } }