package org.jetbrains.appcode.reveal;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.jetbrains.cidr.execution.AppCodeRunConfiguration;
import com.jetbrains.cidr.execution.BuildDestination;
import com.jetbrains.cidr.execution.SimulatedBuildDestination;
import com.jetbrains.cidr.execution.simulator.SimulatorConfiguration;
import com.jetbrains.cidr.xcode.Xcode;
import com.jetbrains.cidr.xcode.frameworks.AppleSdk;
import com.jetbrains.cidr.xcode.model.XCBuildConfiguration;
import icons.AppcodeRevealIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
public class RefreshRevealAction extends AnAction implements AnAction.TransparentUpdate {
public static final Icon ICON = AppcodeRevealIcons.RunWithReveal;
@NotNull private final AppCodeRunConfiguration myConfiguration;
@NotNull private final ExecutionEnvironment myEnvironment;
@NotNull private final ProcessHandler myProcessHandler;
@NotNull private final BuildDestination myDestination;
@NotNull private final String myBundleID;
private boolean myDisabled = false;
public RefreshRevealAction(@NotNull AppCodeRunConfiguration configuration,
@NotNull ExecutionEnvironment environment,
@NotNull ProcessHandler handler,
@NotNull BuildDestination destination,
@NotNull String bundleId) {
myConfiguration = configuration;
myEnvironment = environment;
myProcessHandler = handler;
myDestination = destination;
myBundleID = bundleId;
}
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setIcon(ICON);
String title = "Show in Reveal";
XCBuildConfiguration xcBuildConfiguration = myConfiguration.getConfiguration();
AppleSdk sdk = xcBuildConfiguration == null ? null : xcBuildConfiguration.getBaseSdk();
File lib = null;
boolean compatible = false;
File appBundle = Reveal.getDefaultRevealApplicationBundle();
if (appBundle != null) {
lib = Reveal.getRevealLib(appBundle, sdk);
compatible = Reveal.isCompatible(appBundle);
e.getPresentation().setEnabled(lib != null
&& compatible
&& !myDisabled
&& myProcessHandler.isStartNotified()
&& !myProcessHandler.isProcessTerminating()
&& !myProcessHandler.isProcessTerminated()
);
}
if (lib == null) {
title += " (Reveal library not found)";
}
else if (!compatible) {
title += " (Reveal.app is not compatible, please update)";
}
else if (myDisabled) {
title += " (Action is disabled until configuration relaunch)";
}
e.getPresentation().setText(title, false);
}
@Override
public void actionPerformed(AnActionEvent e) {
Project project = getEventProject(e);
if (project == null) return;
RevealRunConfigurationExtension.RevealSettings settings = RevealRunConfigurationExtension.getRevealSettings(myConfiguration);
if (!settings.autoInject) {
int response = Messages.showYesNoDialog(project,
"Reveal library was not injected.<br><br>" +
"Would you like to enable automatic library injection for this run configuration?<br><br>" +
"You'll need to relaunch the configuration after this change.",
"Reveal", Messages.getQuestionIcon()
);
if (response != Messages.YES) return;
settings.autoInject = true;
RevealRunConfigurationExtension.setRevealSettings(myConfiguration, settings);
myDisabled = true; // disable button until restart
return;
}
File appBundle = Reveal.getDefaultRevealApplicationBundle();
if (appBundle == null) return;
try {
Reveal.refreshReveal(appBundle, myBundleID, getDeviceName(myDestination));
}
catch (ExecutionException ex) {
Reveal.LOG.info(ex);
ExecutionUtil.handleExecutionError(myEnvironment, ex);
}
}
@Nullable
private static String getDeviceName(@NotNull BuildDestination destination) throws ExecutionException {
if (Xcode.getVersion().isOrGreaterThan(8)) {
// Xcode 8's simulators use the host computer's name
return ExecUtil.execAndReadLine(new GeneralCommandLine("scutil", "--get", "ComputerName"));
} else if (destination.isDevice()) {
return destination.getDeviceSafe().getName();
} else if (destination.isSimulator()) {
SimulatedBuildDestination.Simulator simulator = destination.getSimulator();
if (simulator == null) throw new ExecutionException("Simulator not specified.");
switch (simulator.getDeviceFamilyID()) {
case SimulatorConfiguration.IPHONE_FAMILY:
return "iPhone Simulator";
case SimulatorConfiguration.IPAD_FAMILY:
return "iPad Simulator";
case SimulatorConfiguration.TV_FAMILY:
return "Apple TV Simulator";
case SimulatorConfiguration.WATCH_FAMILY:
return "Apple Watch Simulator";
}
throw new ExecutionException("Unknown simulator type: " + simulator);
}
throw new ExecutionException("Unsupported destination: " + destination);
}
}