com.android.tools.idea.editors.theme.NewStyleDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.android.tools.idea.editors.theme.NewStyleDialog.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 com.android.tools.idea.editors.theme;

import com.android.resources.ResourceType;
import com.android.tools.idea.configurations.Configuration;
import com.android.tools.idea.configurations.ThemeSelectionDialog;
import com.android.tools.idea.configurations.ThemeSelectionPanel;
import com.android.tools.idea.editors.theme.attributes.editors.StyleListCellRenderer;
import com.android.tools.idea.res.AppResourceRepository;
import com.android.tools.idea.res.ResourceNameValidator;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class NewStyleDialog extends DialogWrapper {
    private final ResourceNameValidator myResourceNameValidator;
    private JPanel contentPane;
    private JTextField myStyleNameTextField;
    private JLabel myMessageLabel;
    private JLabel myParentStyleLabel;
    private JLabel myStyleNameLabel;
    private JComboBox myParentStyleComboBox;
    /** Message displayed when the style name is empty */
    private final String myEmptyStyleValidationText;
    private @Nullable ThemeSelectionPanel.ThemeChangedListener myThemeChangedListener;

    /**
     * Creates a new style dialog. This dialog it's used both to create new themes and new styles.
     * @param isTheme Whether the new item will be a theme or a regular style. This will only affect the messages displayed to user.
     * @param context The current theme editor context.
     * @param defaultParentName The parent style that will be preselected in the parent text field.
     * @param currentThemeName The current theme name. This is used to automatically generate style names suggestions.
     * @param message Message to display to the user when creating the new style.
     */
    public NewStyleDialog(boolean isTheme, @NotNull ThemeEditorContext context, @Nullable String defaultParentName,
            @Nullable final String currentThemeName, @Nullable String message) {
        super(true);

        if (!Strings.isNullOrEmpty(message)) {
            myMessageLabel.setText(message);
            myMessageLabel.setVisible(true);
        } else {
            myMessageLabel.setVisible(false);
        }

        final Configuration configuration = context.getConfiguration();
        myResourceNameValidator = ResourceNameValidator.create(false,
                AppResourceRepository.getAppResources(configuration.getModule(), true), ResourceType.STYLE);

        String styleTypeString = isTheme ? "theme" : "style";
        setTitle("New " + StringUtil.capitalize(styleTypeString));
        myStyleNameLabel.setText(String.format("New %1$s name:", styleTypeString));
        myParentStyleLabel.setText(String.format("Parent %1$s name:", styleTypeString));
        myEmptyStyleValidationText = String.format("You must specify a %1$s name", styleTypeString);

        myStyleNameTextField.setText(getNewStyleNameSuggestion(defaultParentName, currentThemeName));

        final ThemeResolver themeResolver = context.getThemeResolver();
        final ImmutableList<String> defaultThemeNames = ThemeEditorUtils.getDefaultThemeNames(themeResolver);

        myParentStyleComboBox.setRenderer(new StyleListCellRenderer(context, myParentStyleComboBox));
        final ParentThemesListModel parentThemesListModel = new ParentThemesListModel(defaultThemeNames,
                defaultParentName);
        myParentStyleComboBox.setModel(parentThemesListModel);
        myParentStyleComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String selectedValue = (String) myParentStyleComboBox.getSelectedItem();
                if (ParentThemesListModel.SHOW_ALL_THEMES.equals(selectedValue)) {
                    myParentStyleComboBox.hidePopup();
                    final ThemeSelectionDialog dialog = new ThemeSelectionDialog(configuration);

                    if (myThemeChangedListener != null) {
                        dialog.setThemeChangedListener(myThemeChangedListener);
                    }

                    dialog.show();
                    selectedValue = dialog.isOK() ? dialog.getTheme() : null;
                }
                if (selectedValue == null) {
                    selectedValue = (String) parentThemesListModel.getElementAt(0);
                } else if (!defaultThemeNames.contains(selectedValue)) {
                    parentThemesListModel.removeElement(selectedValue);
                    parentThemesListModel.insertElementAt(selectedValue, 0);
                }
                myParentStyleComboBox.setSelectedItem(selectedValue);
                myStyleNameTextField.setText(getNewStyleNameSuggestion(selectedValue, currentThemeName));
                if (myThemeChangedListener != null) {
                    myThemeChangedListener.themeChanged(selectedValue);
                }
            }
        });

        init();
    }

    @Nullable
    @Override
    protected JComponent createCenterPanel() {
        return contentPane;
    }

    @Nullable
    @Override
    public JComponent getPreferredFocusedComponent() {
        return myStyleNameTextField;
    }

    @Nullable
    @Override
    protected ValidationInfo doValidate() {
        String newStyleName = myStyleNameTextField.getText();
        if (Strings.isNullOrEmpty(newStyleName)) {
            return new ValidationInfo(myEmptyStyleValidationText, myStyleNameTextField);
        }

        if (!myResourceNameValidator.checkInput(newStyleName)) {
            // If checkInput is false, getErrorText will be not null.
            //noinspection ConstantConditions
            return new ValidationInfo(myResourceNameValidator.getErrorText(newStyleName), myStyleNameTextField);
        }

        return super.doValidate();
    }

    @Override
    public void show() {
        if (myThemeChangedListener != null) {
            myThemeChangedListener.themeChanged((String) myParentStyleComboBox.getSelectedItem());
        }
        super.show();
    }

    public String getStyleName() {
        return myStyleNameTextField.getText();
    }

    public String getStyleParentName() {
        return (String) myParentStyleComboBox.getSelectedItem();
    }

    private static final String[] COMMON_THEME_NAMES = { "Material", "Holo", "Leanback", "Micro", "DeviceDefault",
            "AppCompat" };

    /**
     * Returns a suggestion for a new style name based on both the parent style name and the current theme name. It will try to replace parent
     * theme names with the passed theme name.
     * <p/>
     * <p/>For a parent style name like <pre>Widget.Material.Button</pre> and a theme name <pre>MyTheme</pre>, it would generate the name
     * <pre>Widget.MyTheme.Button</pre>
     *
     * @param parentQualifiedName  The parent style name, possibly with "android:" prefix.
     * @param currentThemeName The current theme name.
     */
    @NotNull
    static String getNewStyleNameSuggestion(@Nullable String parentQualifiedName,
            @Nullable String currentThemeName) {
        if (Strings.isNullOrEmpty(parentQualifiedName) || Strings.isNullOrEmpty(currentThemeName)) {
            return "";
        }

        String parentStyleName = ResolutionUtils.getNameFromQualifiedName(parentQualifiedName);
        if (parentStyleName.equals(currentThemeName)) {
            return "";
        }
        currentThemeName = currentThemeName.replace("Theme.", "");
        for (String themeName : COMMON_THEME_NAMES) {
            if (parentStyleName.matches(".*\\b" + themeName + "\\b.*")) {
                // The name it's at the end
                return parentStyleName.replaceFirst("\\b" + themeName + "\\b", currentThemeName);
            }
        }

        return parentStyleName + '.' + currentThemeName;
    }

    public void setThemeChangedListener(@NotNull ThemeSelectionPanel.ThemeChangedListener themeChangedListener) {
        myThemeChangedListener = themeChangedListener;
    }

    public void enableParentChoice(boolean enable) {
        myParentStyleComboBox.setEnabled(enable);
    }
}