com.mobilesorcery.sdk.ui.internal.launch.MoSyncLaunchParamsTab.java Source code

Java tutorial

Introduction

Here is the source code for com.mobilesorcery.sdk.ui.internal.launch.MoSyncLaunchParamsTab.java

Source

/*  Copyright (C) 2009 Mobile Sorcery AB
    
This program is free software; you can redistribute it and/or modify it
under the terms of the Eclipse Public License v1.0.
    
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for
more details.
    
You should have received a copy of the Eclipse Public License v1.0 along
with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html
 */
package com.mobilesorcery.sdk.ui.internal.launch;

import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;

import com.mobilesorcery.sdk.core.CoreMoSyncPlugin;
import com.mobilesorcery.sdk.core.IBuildConfiguration;
import com.mobilesorcery.sdk.core.ILaunchConstants;
import com.mobilesorcery.sdk.core.MoSyncNature;
import com.mobilesorcery.sdk.core.MoSyncProject;
import com.mobilesorcery.sdk.core.launch.AutomaticEmulatorLauncher;
import com.mobilesorcery.sdk.core.launch.IEmulatorLauncher;
import com.mobilesorcery.sdk.core.launch.MoReLauncher;
import com.mobilesorcery.sdk.internal.launch.EmulatorLaunchConfigurationDelegate;
import com.mobilesorcery.sdk.ui.BuildConfigurationsContentProvider;
import com.mobilesorcery.sdk.ui.BuildConfigurationsLabelProvider;
import com.mobilesorcery.sdk.ui.DefaultMessageProvider;
import com.mobilesorcery.sdk.ui.MoSyncProjectSelectionDialog;
import com.mobilesorcery.sdk.ui.MosyncUIPlugin;
import com.mobilesorcery.sdk.ui.UpdateListener.IUpdatableControl;
import com.mobilesorcery.sdk.ui.launch.IEmulatorLaunchConfigurationPart;

public class MoSyncLaunchParamsTab extends AbstractLaunchConfigurationTab implements IUpdatableControl {

    private class TabListener implements ModifyListener, SelectionListener {

        @Override
        public void modifyText(ModifyEvent e) {
            updateLaunchConfigurationDialog();
        }

        @Override
        public void widgetDefaultSelected(SelectionEvent e) {/* do nothing */
        }

        @Override
        public void widgetSelected(SelectionEvent e) {
            Object source = e.getSource();
            if (source == projectButton) {
                handleProjectButtonSelected();
            } else if (source == projectText) {
                updateLaunchConfigurationDialog();
            } else {
                updateLaunchConfigurationDialog();
            }
        }
    }

    private class UpdateConfigurationListener implements ModifyListener {
        @Override
        public void modifyText(ModifyEvent e) {
            updateConfigurations();
            if (e.getSource() == projectText) {
                updateLaunchDelegateList();
            }
        }
    }

    private Text projectText;
    private Button projectButton;
    private final TabListener listener = new TabListener();
    private IProject project;
    private String mode;
    private Button changeConfiguration;
    private ComboViewer configurations;
    private Group configurationGroup;
    private String[] debugBuildConfigurationTypes = new String[] { IBuildConfiguration.DEBUG_TYPE };
    private String[] buildConfigurationTypes = new String[] { IBuildConfiguration.RELEASE_TYPE };
    private ComboViewer launchDelegateList;
    private Composite launchDelegateHolder;
    private StackLayout launchDelegateHolderLayout;
    private final HashMap<String, Composite> delegateComposites = new HashMap<String, Composite>();
    private ILaunchConfiguration config;
    private final HashMap<String, IEmulatorLaunchConfigurationPart> launcherParts = new HashMap<String, IEmulatorLaunchConfigurationPart>();
    private final HashSet<IEmulatorLaunchConfigurationPart> initedParts = new HashSet<IEmulatorLaunchConfigurationPart>();
    private Composite launchDelegateHolderParent;
    private boolean allowsExternalEmulators;
    private String currentLaunchDelegateId;

    @Override
    public void createControl(Composite parent) {
        Composite control = new Composite(parent, SWT.NONE);
        control.setLayout(new GridLayout(1, false));
        createProjectEditor(control);
        if (allowsExternalEmulators) {
            createLaunchDelegateEditor(control);
        }
        createConfigurationEditor(control);
        setControl(control);
    }

    private void createLaunchDelegateEditor(Composite control) {
        Set<String> ids = sortLaunchers(CoreMoSyncPlugin.getDefault().getEmulatorLauncherIds());
        launchDelegateHolderParent = control;

        Group launchDelegateGroup = new Group(control, SWT.NONE);
        launchDelegateGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
        launchDelegateGroup.setText("&Emulator");
        launchDelegateGroup.setLayout(new GridLayout(1, false));
        launchDelegateList = new ComboViewer(launchDelegateGroup);
        launchDelegateList.setContentProvider(new ArrayContentProvider());
        launchDelegateList.setInput(filterLaunchDelegateIds(ids).toArray());
        launchDelegateList.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                return CoreMoSyncPlugin.getDefault().getEmulatorLauncher((String) element).getName();
            }
        });
        launchDelegateList.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                String id = (String) selection.getFirstElement();
                switchDelegate(id, false);
            }
        });
        launchDelegateList.getCombo().addModifyListener(listener);
        launchDelegateHolderParent = launchDelegateGroup;

        launchDelegateHolder = new Composite(launchDelegateHolderParent, SWT.NONE);
        launchDelegateHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        launchDelegateHolderLayout = new StackLayout();
        launchDelegateHolder.setLayout(launchDelegateHolderLayout);

        switchDelegate(MoReLauncher.ID, true);
    }

    private Set<String> sortLaunchers(Set<String> emulatorLauncherIds) {
        TreeSet<String> sortedLaunchers = new TreeSet<String>(new Comparator<String>() {
            @Override
            public int compare(String id1, String id2) {
                if (id1.equals(id2)) {
                    return 0;
                }
                int score1 = getLauncherScore(id1);
                int score2 = getLauncherScore(id2);
                if (score1 != score2) {
                    return score2 - score1;
                }
                return id1.compareTo(id2);
            }

            private int getLauncherScore(String id) {
                if (AutomaticEmulatorLauncher.ID.equals(id)) {
                    return 2;
                } else if (MoReLauncher.ID.equals(id)) {
                    return 1;
                }
                return 0;
            }
        });
        sortedLaunchers.addAll(emulatorLauncherIds);
        return sortedLaunchers;
    }

    protected void switchDelegate(String id, boolean updateCombo) {
        Composite delegateComposite = delegateComposites.get(id);
        if (delegateComposite == null) {
            delegateComposite = createDelegateComposite(id, launchDelegateHolder);
            delegateComposites.put(id, delegateComposite);
        }

        initLauncherPart(id);
        if (updateCombo) {
            this.launchDelegateList.setSelection(new StructuredSelection(id));
        }
        launchDelegateHolderLayout.topControl = delegateComposite;
        currentLaunchDelegateId = id;
        launchDelegateHolder.layout();
        validateCurrentLaunchDelegate();
        updateLaunchConfigurationDialog();
    }

    private void initLauncherPart(String id) {
        IEmulatorLaunchConfigurationPart launcherPart = launcherParts.get(id);
        if (config != null && launcherPart != null && !initedParts.contains(launcherPart)) {
            try {
                launcherPart.init(config);
            } catch (CoreException e) {
                CoreMoSyncPlugin.getDefault().log(e);
            } finally {
                if (launcherPart != null) {
                    initedParts.add(launcherPart);
                }
            }
        }
    }

    private Composite createDelegateComposite(String id, Composite parent) {
        IEmulatorLaunchConfigurationPart launcherPart = MosyncUIPlugin.getDefault().getEmulatorLauncherPart(id);
        if (launcherPart == null) {
            return new Composite(parent, SWT.NONE);
        }
        launcherParts.put(id, launcherPart);
        Composite control = launcherPart.createControl(parent, this);
        control.setLayoutData(new GridData(GridData.FILL_BOTH));
        return control;
    }

    private IProject selectProject() {
        MoSyncProjectSelectionDialog dialog = new MoSyncProjectSelectionDialog(getShell());
        dialog.setInitialProject(getProject());
        return dialog.selectProject();
    }

    private void createConfigurationEditor(Composite control) {
        configurationGroup = new Group(control, SWT.NONE);
        configurationGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        configurationGroup.setText("&Configuration");
        configurationGroup.setLayout(new GridLayout(1, false));

        changeConfiguration = new Button(configurationGroup, SWT.CHECK);
        changeConfiguration.setText(isDebugMode() ? "&Automatically switch to this configuration before debugging"
                : "&Automatically switch to this configuration before launching");
        changeConfiguration.addSelectionListener(listener);

        configurations = new ComboViewer(configurationGroup, SWT.READ_ONLY | SWT.BORDER);
        configurations.getCombo().addSelectionListener(listener);
    }

    private void updateConfigurations() {
        MoSyncProject project = selectedProject();
        if (project != null) {
            configurations.setContentProvider(new BuildConfigurationsContentProvider(project,
                    isDebugMode() ? debugBuildConfigurationTypes : buildConfigurationTypes));
            configurations.setLabelProvider(new BuildConfigurationsLabelProvider(project));
            configurations.setInput(project);
        }
    }

    private void updateLaunchDelegateList() {
        if (launchDelegateList != null) {
            Set<String> ids = filterLaunchDelegateIds(CoreMoSyncPlugin.getDefault().getEmulatorLauncherIds());
            launchDelegateList.setInput(ids.toArray());
            updateLaunchDelegateListSelection(this.config);
        }
    }

    /**
     * Updates the selection in the launchDelegate list according to the
     * current launch configuration.
     *
     * @param config The current launch configuration, if config is null the
     *               default config is used.
     */
    private void updateLaunchDelegateListSelection(ILaunchConfiguration config) {
        if (launchDelegateList == null) {
            return;
        }

        if (config == null) {
            launchDelegateList.setSelection(new StructuredSelection(MoReLauncher.ID));
            return;
        }

        try {
            String launchConfigId = config.getAttribute(ILaunchConstants.LAUNCH_DELEGATE_ID, MoReLauncher.ID);
            launchDelegateList.setSelection(new StructuredSelection(launchConfigId));
        } catch (CoreException ce) {
            // If we cannot find the id, use the default.
            launchDelegateList.setSelection(new StructuredSelection(MoReLauncher.ID));
        }
    }

    private Set<String> filterLaunchDelegateIds(Set<String> emulatorLauncherIds) {
        Set<String> result = new HashSet<String>();
        for (String id : emulatorLauncherIds) {
            IEmulatorLauncher launcher = CoreMoSyncPlugin.getDefault().getEmulatorLauncher(id);
            if (launcher != null && config != null) {
                /*int availability = launcher.isAvailable(config, mode);
                if (availability == IEmulatorLauncher.AVAILABLE || availability == IEmulatorLauncher.REQUIRES_CONFIGURATION) {
                   result.add(id);
                }*/
                if (launcher.supportsLaunchMode(mode) || MoReLauncher.ID.equals(id)) {
                    result.add(id);
                }
            }
        }
        return sortLaunchers(result);
    }

    public void setBuildConfigurationTypes(boolean isDebug, String... types) {
        if (isDebug) {
            debugBuildConfigurationTypes = types;
        } else {
            buildConfigurationTypes = types;
        }
    }

    protected void handleProjectButtonSelected() {
        IProject project = selectProject();
        if (project == null) {
            return;
        }

        String projectName = project.getName();
        projectText.setText(projectName);
    }

    private IWorkspaceRoot getWorkspaceRoot() {
        return ResourcesPlugin.getWorkspace().getRoot();
    }

    protected void createProjectEditor(Composite parent) {
        Font font = parent.getFont();
        Group group = new Group(parent, SWT.NONE);
        group.setText("Project");
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        group.setLayoutData(gd);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        group.setLayout(layout);
        group.setFont(font);
        projectText = new Text(group, SWT.SINGLE | SWT.BORDER);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        projectText.setLayoutData(gd);
        projectText.setFont(font);
        projectText.addModifyListener(listener);
        projectText.addModifyListener(new UpdateConfigurationListener());
        projectButton = createPushButton(group, "Browse...", null);
        projectButton.addSelectionListener(listener);
    }

    @Override
    public String getName() {
        return "Main";
    }

    @Override
    public void initializeFrom(ILaunchConfiguration config) {
        try {
            this.config = config;
            projectText.setText(config.getAttribute(ILaunchConstants.PROJECT, ""));
            initializeBuildConfigurationOptions(config);
            updateLaunchConfigurationDialog();
            updateLaunchDelegateListSelection(config);
        } catch (Exception e) {
            e.printStackTrace();
            // Ignore.
        }
    }

    public void initializeBuildConfigurationOptions(ILaunchConfiguration config) throws CoreException {
        String defaultBuildConfig = EmulatorLaunchConfigurationDelegate
                .getDefaultBuildConfiguration(MoSyncProject.create(getProject()), mode);
        changeConfiguration.setSelection(config.getAttribute(getAutoChangeConfigKey(), false));
        String buildConfiguration = config.getAttribute(getBuildConfigKey(), defaultBuildConfig);
        configurations.setSelection(new StructuredSelection(buildConfiguration));
    }

    private boolean isDebugMode() {
        return "debug".equals(mode);
    }

    private String getAutoChangeConfigKey() {
        return isDebugMode() ? ILaunchConstants.AUTO_CHANGE_CONFIG_DEBUG : ILaunchConstants.AUTO_CHANGE_CONFIG;
    }

    private String getBuildConfigKey() {
        return isDebugMode() ? ILaunchConstants.BUILD_CONFIG_DEBUG : ILaunchConstants.BUILD_CONFIG;
    }

    private String getCurrentLauncherDelegateId() {
        String delegateId = MoReLauncher.ID;
        if (launchDelegateList != null) {
            IStructuredSelection selection = (IStructuredSelection) launchDelegateList.getSelection();
            delegateId = (String) selection.getFirstElement();
        }

        return delegateId;
    }

    @Override
    public void performApply(ILaunchConfigurationWorkingCopy copy) {
        for (IEmulatorLaunchConfigurationPart launcherPart : launcherParts.values()) {
            if (initedParts.contains(launcherPart)) {
                launcherPart.apply(copy);
            }
        }
        copy.setAttribute(ILaunchConstants.PROJECT, projectText.getText().trim());
        copy.setAttribute(getAutoChangeConfigKey(), changeConfiguration.getSelection());
        copy.setAttribute(getBuildConfigKey(), getSelectedBuildConfiguration());
        copy.setAttribute(ILaunchConstants.LAUNCH_DELEGATE_ID, getCurrentLauncherDelegateId());
    }

    public String getSelectedBuildConfiguration() {
        String result = (String) ((IStructuredSelection) configurations.getSelection()).getFirstElement();
        return result == null ? "" : result;
    }

    @Override
    public void setDefaults(ILaunchConfigurationWorkingCopy wc) {
        EmulatorLaunchConfigurationDelegate.configureLaunchConfigForSourceLookup(wc);
    }

    private IProject getProject() {
        return project;
    }

    public void setMode(String mode) {
        this.mode = mode;
    }

    @Override
    public void updateLaunchConfigurationDialog() {
        if (changeConfiguration == null) {
            return;
        }
        MoSyncProject project = selectedProject();
        boolean configurationsVisible = project != null && project.areBuildConfigurationsSupported();
        boolean comboEnabled = changeConfiguration.getSelection() && configurationsVisible;
        configurations.getControl().setEnabled(comboEnabled);
        configurationGroup.setVisible(configurationsVisible);

        if (launchDelegateHolderParent != null) {
            launchDelegateHolderParent.setVisible(project != null);
        }

        super.updateLaunchConfigurationDialog();
    }

    private MoSyncProject selectedProject() {
        MoSyncProject newProject = null;
        try {
            project = getWorkspaceRoot().getProject(projectText.getText().trim());
            if (project != null && project.exists() && project.isOpen() && project.hasNature(MoSyncNature.ID)) {
                newProject = MoSyncProject.create(project);
            }

        } catch (Exception e) {
            // Ignore.
        }

        return newProject;
    }

    @Override
    public void updateUI() {
        updateConfigurations();
        validateCurrentLaunchDelegate();
        updateLaunchConfigurationDialog();
    }

    private void validateCurrentLaunchDelegate() {
        IEmulatorLaunchConfigurationPart launcherPart = launcherParts.get(currentLaunchDelegateId);
        if (launcherPart != null) {
            IMessageProvider validationResult = launcherPart.validate();
            if (DefaultMessageProvider.isEmpty(validationResult)) {
                setErrorMessage(null);
            } else {
                setErrorMessage(validationResult.getMessage());
            }
        }
    }

    public void setAllowExternalEmulators(boolean allowsExternalEmulators) {
        this.allowsExternalEmulators = allowsExternalEmulators;
    }
}