com.android.tools.idea.run.CloudConfigurationComboBox.java Source code

Java tutorial

Introduction

Here is the source code for com.android.tools.idea.run.CloudConfigurationComboBox.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.run;

import com.android.tools.idea.run.CloudConfiguration.Kind;
import com.google.common.collect.Maps;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Pair;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.ui.SimpleTextAttributes;
import org.jdesktop.swingx.combobox.ListComboBoxModel;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.run.AndroidRunConfigurationBase;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Map;

/**
 * {@link CloudConfigurationComboBox} displays the list of cloud configurations obtained from the cloud provider
 * in a ComboboxWithBrowseButton.
 *
 * When the browse action is invoked, it delegates to the provider to display a more detailed dialog where the list of device matrices
 * can be updated. The model is updated on return from that dialog, since users could have changed the list of configurations. This
 * change is also propagated to other instances of this class via the {@link CloudConfigurationCoordinator}.
 */
public class CloudConfigurationComboBox extends ComboboxWithBrowseButton {
    private final Kind myConfigurationKind;
    private AndroidRunConfigurationBase myCurrentAndroidConfiguration;
    private Module myCurrentModule;
    private AndroidFacet myCurrentFacet;
    private List<? extends CloudConfiguration> myTestingConfigurations;
    private ActionListener myActionListener;
    private final CloudConfigurationProvider myConfigurationProvider;

    // Used to keep track of user choices when run config and/or module are not available.
    private static Map<Kind, CloudConfiguration> myLastChosenCloudConfigurationPerKind = Maps
            .newHashMapWithExpectedSize(5);

    /** A cache of matrix configurations selected by <kind, module> per android run configuration, so that if
     * the android configuration and/or module selections change back and forth, we retain the appropriate selected matrix configuration.
     */
    private static Map<AndroidRunConfigurationBase, Map<Pair<Kind, Module>, CloudConfiguration>> myMatrixConfigurationByAndroidConfigurationAndModuleCache = Maps
            .newHashMapWithExpectedSize(5);

    public CloudConfigurationComboBox(@NotNull Kind configurationKind) {
        myConfigurationKind = configurationKind;
        myConfigurationProvider = CloudConfigurationProvider.getCloudConfigurationProvider();
        setMinimumSize(new Dimension(100, getMinimumSize().height));

        getComboBox().setRenderer(new TestConfigurationRenderer());
        getComboBox().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Object item = getComboBox().getSelectedItem();
                if (item instanceof CloudConfiguration) {
                    CloudConfiguration cloudConfiguration = (CloudConfiguration) item;
                    myLastChosenCloudConfigurationPerKind.put(myConfigurationKind, cloudConfiguration);
                    if (myCurrentAndroidConfiguration != null && myCurrentModule != null) {
                        Map<Pair<Kind, Module>, CloudConfiguration> matrixConfigurationByModuleCache = myMatrixConfigurationByAndroidConfigurationAndModuleCache
                                .get(myCurrentAndroidConfiguration);
                        if (matrixConfigurationByModuleCache == null) {
                            matrixConfigurationByModuleCache = Maps.newHashMapWithExpectedSize(5);
                            myMatrixConfigurationByAndroidConfigurationAndModuleCache
                                    .put(myCurrentAndroidConfiguration, matrixConfigurationByModuleCache);
                        }
                        matrixConfigurationByModuleCache.put(Pair.create(myConfigurationKind, myCurrentModule),
                                cloudConfiguration);
                    }
                }
            }
        });

        CloudConfigurationCoordinator.getInstance(myConfigurationKind).addComboBox(this);
    }

    public void setFacet(@NotNull AndroidFacet facet) {
        if (!CloudConfigurationProvider.isEnabled()) {
            return; // Running tests in cloud is not enabled!
        }

        myCurrentFacet = facet;
        myCurrentModule = myCurrentFacet.getModule();
        myTestingConfigurations = myConfigurationProvider.getCloudConfigurations(myCurrentFacet,
                myConfigurationKind);

        // Since setFacet can be called multiple times, make sure to remove any previously registered listeners.
        removeActionListener(myActionListener);

        myActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                CloudConfiguration selectedConfig = myConfigurationProvider.openMatrixConfigurationDialog(
                        myCurrentFacet, (CloudConfiguration) getComboBox().getSelectedItem(), myConfigurationKind);
                // Update the comboboxes' contents even if selectedConfig is null since it might mean that a user deleted
                // all configurations in the Matrix Configuration dialog.
                List<? extends CloudConfiguration> cloudConfigurations = myConfigurationProvider
                        .getCloudConfigurations(myCurrentFacet, myConfigurationKind);
                CloudConfigurationCoordinator.getInstance(myConfigurationKind)
                        .updateComboBoxesWithNewCloudConfigurations(cloudConfigurations, myCurrentModule);
                if (cloudConfigurations.isEmpty() || selectedConfig != null) {
                    getComboBox().setSelectedItem(selectedConfig);
                }
                getComboBox().updateUI();
            }
        };
        addActionListener(myActionListener);

        updateContent();
    }

    public void setConfiguration(@NotNull AndroidRunConfigurationBase configuration) {
        myCurrentAndroidConfiguration = configuration;
    }

    @Override
    public void dispose() {
        CloudConfigurationCoordinator.getInstance(myConfigurationKind).removeComboBox(this);
        super.dispose();
    }

    public void selectConfiguration(int id) {
        if (myTestingConfigurations != null) {
            for (CloudConfiguration configuration : myTestingConfigurations) {
                if (configuration.getId() == id) {
                    getComboBox().setSelectedItem(configuration);
                    return;
                }
            }
        }
    }

    private void updateContent() {
        if (myCurrentModule == null || myCurrentModule.isDisposed()) {
            return;
        }

        getComboBox().setModel(new ListComboBoxModel(myTestingConfigurations));

        if (myCurrentAndroidConfiguration == null) {
            CloudConfiguration cloudConfiguration = myLastChosenCloudConfigurationPerKind.get(myConfigurationKind);
            if (cloudConfiguration != null && myTestingConfigurations.contains(cloudConfiguration)) {
                getComboBox().setSelectedItem(cloudConfiguration);
            }
        } else {
            Map<Pair<Kind, Module>, CloudConfiguration> matrixConfigurationByModuleCache = myMatrixConfigurationByAndroidConfigurationAndModuleCache
                    .get(myCurrentAndroidConfiguration);
            if (matrixConfigurationByModuleCache != null) {
                CloudConfiguration selectedConfig = matrixConfigurationByModuleCache
                        .get(Pair.create(myConfigurationKind, myCurrentModule));
                if (selectedConfig != null && myTestingConfigurations.contains(selectedConfig)) {
                    getComboBox().setSelectedItem(selectedConfig);
                }
            }
        }
    }

    public void updateCloudConfigurations(List<? extends CloudConfiguration> cloudConfigurations, Module module) {
        if (myCurrentFacet != null && myCurrentModule.equals(module)) {
            myTestingConfigurations = cloudConfigurations;
            int selectedConfigurationId = -1;
            Object selectedItem = getComboBox().getSelectedItem();
            if (selectedItem != null) {
                selectedConfigurationId = ((CloudConfiguration) selectedItem).getId();
            }
            updateContent();
            selectConfiguration(selectedConfigurationId);
        }
    }

    private static class TestConfigurationRenderer extends ColoredListCellRenderer {
        @Override
        protected void customizeCellRenderer(JList list, Object value, int index, boolean selected,
                boolean hasFocus) {
            if (value == null) {
                append("[none]", SimpleTextAttributes.ERROR_ATTRIBUTES);
            } else if (value instanceof CloudConfiguration) {
                CloudConfiguration config = (CloudConfiguration) value;
                append(config.getDisplayName(),
                        config.getDeviceConfigurationCount() < 1 ? SimpleTextAttributes.ERROR_ATTRIBUTES
                                : SimpleTextAttributes.REGULAR_ATTRIBUTES);
                setIcon(config.getIcon());
            }
        }
    }
}