package com.mobilesorcery.sdk.builder.iphoneos.launch; import java.io.File; import java.text.MessageFormat; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jface.util.Util; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import com.mobilesorcery.sdk.builder.iphoneos.Activator; import com.mobilesorcery.sdk.builder.iphoneos.IPhoneOSPackager; import com.mobilesorcery.sdk.builder.iphoneos.IPhoneSimulator; import com.mobilesorcery.sdk.builder.iphoneos.SDK; import com.mobilesorcery.sdk.builder.iphoneos.XCodeBuild; import com.mobilesorcery.sdk.builder.iphoneos.ui.dialogs.ConfigureXcodeDialog; import com.mobilesorcery.sdk.core.BuildVariant; import com.mobilesorcery.sdk.core.CoreMoSyncPlugin; import com.mobilesorcery.sdk.core.IBuildVariant; import com.mobilesorcery.sdk.core.IPackager; import com.mobilesorcery.sdk.core.MoSyncProject; import com.mobilesorcery.sdk.core.Version; import com.mobilesorcery.sdk.core.launch.AbstractEmulatorLauncher; import com.mobilesorcery.sdk.core.launch.IEmulatorLauncher; import com.mobilesorcery.sdk.internal.launch.EmulatorLaunchConfigurationDelegate; public class IPhoneEmulatorLauncher extends AbstractEmulatorLauncher { public final static String SDK_ATTR = "iphone.sdk"; private static final String ID = "com.mobilesorcery.sdk.builder.iphoneos.launcher"; public IPhoneEmulatorLauncher() { super("iPhone Simulator"); } @Override public int isLaunchable(ILaunchConfiguration launchConfiguration, String mode) { if (!Util.isMac()) { return UNLAUNCHABLE; } else if (!isCorrectPackager(launchConfiguration)) { return IEmulatorLauncher.UNLAUNCHABLE; } if (shouldAskUserForLauncher(launchConfiguration, mode)) { return IEmulatorLauncher.REQUIRES_CONFIGURATION; } else if (!isCorrectlyInstalled()) { IEmulatorLauncher preferredLauncher = CoreMoSyncPlugin.getDefault().getPreferredLauncher(IPhoneOSPackager.ID); boolean useOtherLauncher = !shouldAskUserForLauncher(IPhoneOSPackager.ID) && !Util.equals(preferredLauncher.getId(), ID); return isAutoSelectLaunch(launchConfiguration, mode) && useOtherLauncher ? IEmulatorLauncher.UNLAUNCHABLE : IEmulatorLauncher.REQUIRES_CONFIGURATION; } else { return super.isLaunchable(launchConfiguration, mode); } } private boolean shouldAskUserForLauncher(ILaunchConfiguration launchConfiguration, String mode) { return isCorrectlyInstalled() && isAutoSelectLaunch(launchConfiguration, mode) && shouldAskUserForLauncher(IPhoneOSPackager.ID); } @Override public void launch(ILaunchConfiguration launchConfig, String mode, ILaunch launch, int emulatorId, IProgressMonitor monitor) throws CoreException { IPhoneSimulator sim = IPhoneSimulator.createDefault(); sim.assertValid(); // TODO: Incremental building if we change the SDK!? IProject project = EmulatorLaunchConfigurationDelegate.getProject(launchConfig); MoSyncProject mosyncProject = MoSyncProject.create(project); SDK sdk = Activator.getDefault().getSDK(mosyncProject, XCodeBuild.IOS_SIMULATOR_SDKS); Version sdkVersion = sdk == null ? null : sdk.getVersion(); File pathToApp = getPackageToInstall(launchConfig, mode); String family = getFamily(getVariant(launchConfig, mode)); Process process = sim.runApp(new Path(pathToApp.getAbsolutePath()), sdkVersion == null ? null : sdkVersion.toString(), family); DebugPlugin.newProcess(launch, process, MessageFormat.format("iPhone Simulator {0}", sdk.getVersion())); } private String getFamily(IBuildVariant variant) { // Hard-coded, we may want to get this from device db instead. if (variant.getProfile().getName().contains("iPad")) { return "ipad"; } return null; } @Override public IBuildVariant getVariant(ILaunchConfiguration launchConfig, String mode) throws CoreException { IBuildVariant prototype = super.getVariant(launchConfig, mode); BuildVariant modified = new BuildVariant(prototype); modified.setSpecifier(Activator.IOS_SIMULATOR_SPECIFIER, Activator.IOS_SIMULATOR_SPECIFIER); return modified; } @Override public IEmulatorLauncher configure(ILaunchConfiguration config, String mode) { XCodeBuild.getDefault().refresh(); Display d = PlatformUI.getWorkbench().getDisplay(); // If we are not auto-select, don't fallback to MoRe. final boolean isAutomaticSelection = isAutoSelectLaunch(config, mode); // And if we are supposed to ask the user, we do not really need to configure anything. final boolean needsConfig = !shouldAskUserForLauncher(config, mode); final IEmulatorLauncher[] result = new IEmulatorLauncher[] { null }; d.syncExec(new Runnable() { @Override public void run() { // OK, figure out after 2.6 release where to really put this ui stuff! Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); ConfigureXcodeDialog configureDialog = new ConfigureXcodeDialog(shell); configureDialog.setIsAutomaticSelection(isAutomaticSelection); configureDialog.setNeedsConfig(needsConfig); configureDialog.open(); result[0] = configureDialog.getSelectedLauncher(); } }); return result[0]; } @Override public int getLaunchType(IPackager packager) { return Util.equals(packager.getId(), IPhoneOSPackager.ID) && Util.isMac() ? LAUNCH_TYPE_NATIVE : LAUNCH_TYPE_NONE; } protected boolean isCorrectlyInstalled() { return XCodeBuild.getDefault().isValid() && XCodeBuild.getDefault().listSDKs(XCodeBuild.IOS_SIMULATOR_SDKS).size() > 0; } }